toString() 方法中没有发生递归
Recursion not occurring in toString()-method
我正在创建一个包含 Bag
s 和 Item
s 的复合模式,其中 Bag
s 可以包含 Item
s 但 Item
s它不能包含任何东西。
当我在根上使用 toString()
方法时,我希望 Bag
中的每个 Entity
都打印在 "natural language" 中。目前看来 toString()
方法中的递归被破坏了,我不确定为什么。我尝试在 while
循环之前使用 System.out.println(1);
,但它只打印了一次,这就是我认为递归被破坏的原因。
Item
-class;
public class Item extends Entity {
public Item(String theName) {
this.name = theName;
}
public String toString() {
String output = String.format("a %s", name);
return output;
}
}
Bag
-class
import java.util.*;
public class Bag extends Entity {
private List<Entity> children = new ArrayList<Entity>();
public Bag(String theName) {
this.name = theName;
}
public void add(Entity entity) {
children.add(entity);
}
public String toString() {
String output = String.format("a %s", name);
Iterator<Entity> itemIterator = children.iterator();
output += " containing ";
Entity current = itemIterator.next();
while (itemIterator.hasNext()) {
output += current.toString();
Entity next = itemIterator.next();
if (next instanceof Item) {
output += ", ";
} else if (next instanceof Bag) {
output += " and ";
}
current = next;
}
return output;
}
}
Entity
-class;
public abstract class Entity {
protected String name;
protected int weight;
public abstract String toString();
public abstract int getWeight();
}
MyFrame
包含 main
-方法;
public class MyFrame {
public static void main(String[] args) {
Bag sack = new Bag("sack");
Bag pouch = new Bag("pouch");
Bag suitcase = new Bag("suitcase");
Item perfume = new Item("perfume");
Item deodorant = new Item("deodorant");
Item toothbrush = new Item("toothbrush");
Item hairtie = new Item("hairtie");
Item pen = new Item("pen");
Item sock = new Item("sock");
Item shirt = new Item("white shirt");
Item shirt2 = new Item("black shirt");
pouch.add(toothbrush);
pouch.add(perfume);
pouch.add(deodorant);
sack.add(pen);
sack.add(hairtie);
sack.add(sock);
sack.add(pouch);
suitcase.add(shirt);
suitcase.add(shirt2);
suitcase.add(sack);
System.out.println(suitcase.toString());
}
}
我要的文字是;
"a suitcase containing a white shirt, a black shirt and a sack containing a pen, a hairtie, a sock and a pouch containing a toothbrush, a perfume, a deodorant"
我得到的文字是;
"a suitcase containing a white shirt, a black shirt and"
你在 while 条件下出错
if (!itemIterator.hasNext()) return output;
Entity current = itemIterator.next();
while (true) {
output += current.toString();
if (!itemIterator.hasNext()) break;
Entity next = itemIterator.next();
// ......
current = next;
}
return output;
你基本上跳过了最后一个实体
改变
return output;
到
return output + current;
您没有将最后一个元素附加到输出中。
此外,你在检查Iterator::hasNext
之前调用Iterator::next
,如果你有一个空的Bag
,就会有一个NoSuchElementException
。
迭代器的使用在其他答案中已经被批评了;还应注意边界条件:0 或 1 children.
public String toString() {
String output = String.format("a %s", name);
if (!children.isEmpty()) {
// Unfortunately because of the recursion the following
// cannot be done.
//String list = children.stream()
// .map(Entity::toString).collect(Collectors.join(", "));
//output += list.replaceFirst(", ([^,]*)$", " and ");
// Iterating from the back reversed, allows an easy
// discrimination of comma and "and."
StringBuilder list = new StringBuilder();
String separator = " and ";
ListIterator<Entity> itemIterator = children.listIterator(children.size());
while (itemIterator.hasPrevious()) {
Entity entity = itemIterator.previous();
list.insert(0, entity.toString());
if (itemIterator.hasPrevious()) {
list.insert(0, separator);
separator = ", ";
}
}
output += list.toString();
}
return output;
}
我正在创建一个包含 Bag
s 和 Item
s 的复合模式,其中 Bag
s 可以包含 Item
s 但 Item
s它不能包含任何东西。
当我在根上使用 toString()
方法时,我希望 Bag
中的每个 Entity
都打印在 "natural language" 中。目前看来 toString()
方法中的递归被破坏了,我不确定为什么。我尝试在 while
循环之前使用 System.out.println(1);
,但它只打印了一次,这就是我认为递归被破坏的原因。
Item
-class;
public class Item extends Entity {
public Item(String theName) {
this.name = theName;
}
public String toString() {
String output = String.format("a %s", name);
return output;
}
}
Bag
-class
import java.util.*;
public class Bag extends Entity {
private List<Entity> children = new ArrayList<Entity>();
public Bag(String theName) {
this.name = theName;
}
public void add(Entity entity) {
children.add(entity);
}
public String toString() {
String output = String.format("a %s", name);
Iterator<Entity> itemIterator = children.iterator();
output += " containing ";
Entity current = itemIterator.next();
while (itemIterator.hasNext()) {
output += current.toString();
Entity next = itemIterator.next();
if (next instanceof Item) {
output += ", ";
} else if (next instanceof Bag) {
output += " and ";
}
current = next;
}
return output;
}
}
Entity
-class;
public abstract class Entity {
protected String name;
protected int weight;
public abstract String toString();
public abstract int getWeight();
}
MyFrame
包含 main
-方法;
public class MyFrame {
public static void main(String[] args) {
Bag sack = new Bag("sack");
Bag pouch = new Bag("pouch");
Bag suitcase = new Bag("suitcase");
Item perfume = new Item("perfume");
Item deodorant = new Item("deodorant");
Item toothbrush = new Item("toothbrush");
Item hairtie = new Item("hairtie");
Item pen = new Item("pen");
Item sock = new Item("sock");
Item shirt = new Item("white shirt");
Item shirt2 = new Item("black shirt");
pouch.add(toothbrush);
pouch.add(perfume);
pouch.add(deodorant);
sack.add(pen);
sack.add(hairtie);
sack.add(sock);
sack.add(pouch);
suitcase.add(shirt);
suitcase.add(shirt2);
suitcase.add(sack);
System.out.println(suitcase.toString());
}
}
我要的文字是; "a suitcase containing a white shirt, a black shirt and a sack containing a pen, a hairtie, a sock and a pouch containing a toothbrush, a perfume, a deodorant"
我得到的文字是; "a suitcase containing a white shirt, a black shirt and"
你在 while 条件下出错
if (!itemIterator.hasNext()) return output;
Entity current = itemIterator.next();
while (true) {
output += current.toString();
if (!itemIterator.hasNext()) break;
Entity next = itemIterator.next();
// ......
current = next;
}
return output;
你基本上跳过了最后一个实体
改变
return output;
到
return output + current;
您没有将最后一个元素附加到输出中。
此外,你在检查Iterator::hasNext
之前调用Iterator::next
,如果你有一个空的Bag
,就会有一个NoSuchElementException
。
迭代器的使用在其他答案中已经被批评了;还应注意边界条件:0 或 1 children.
public String toString() {
String output = String.format("a %s", name);
if (!children.isEmpty()) {
// Unfortunately because of the recursion the following
// cannot be done.
//String list = children.stream()
// .map(Entity::toString).collect(Collectors.join(", "));
//output += list.replaceFirst(", ([^,]*)$", " and ");
// Iterating from the back reversed, allows an easy
// discrimination of comma and "and."
StringBuilder list = new StringBuilder();
String separator = " and ";
ListIterator<Entity> itemIterator = children.listIterator(children.size());
while (itemIterator.hasPrevious()) {
Entity entity = itemIterator.previous();
list.insert(0, entity.toString());
if (itemIterator.hasPrevious()) {
list.insert(0, separator);
separator = ", ";
}
}
output += list.toString();
}
return output;
}