EDIT 这已通过使用此线程中建议的StringBuilder解决。谢谢:D
你好,
我有一棵树,我正在尝试按顺序返回内容的字符串。
我现在可以用这样的东西打印出树:
public void inOrder() {
if (left != null) left.inOrder();
System.out.print(content + " ");
if (right != null) right.inOrder();
}
但我想要做的是返回String(而不是在递归时打印出每个节点内容),我无法弄清楚如何做到这一点。我尝试了下面代码的许多变体,但它只返回它在递归中找到的最后一个元素。
public String inOrder(String string) {
if (left != null) left.inOrder(string);
string += content;
if (right != null) right.inOrder(string);
return string;
}
答案 0 :(得分:5)
字符串在java中是不可变的。您没有将新String连接到旧String,您正在创建新String并使string
变量指向它。结果是您在不同的时间点有许多不相关的字符串和string
变量指向它们。
您需要将可变对象传递给您的函数,例如StringBuilder
。此解决方案具有额外的优势,因为它可以避免不必要的对象分配,因此效率更高。
答案 1 :(得分:3)
如果你想用字符串连接做这个,你的第二个例子几乎可以工作 - 问题只在于你丢弃了递归调用的结果。
/**
* creates an Inorder-string-view of this tree and appends it to the given string.
* @return the new String.
*/
public String inOrder(String string) {
if (left != null)
string = left.inOrder(string);
string += content;
if (right != null)
string = right.inOrder(string);
return string;
}
但这是(对于较大的树)可怕的低效率,因为每个+=
实际上创建一个新的String,复制string
和content
的字符 - 因此每个内容字符串都在事实复制the number of later nodes
(按顺序)次数(+1)。一个更好的方法是:
public String inOrder() {
String leftS; String rightS;
if (left != null)
leftS = left.inOrder();
else
leftS = "";
if (right != null)
rightS = right.inOrder();
else
rightS = "";
return leftS + content + rightS;
}
或者更短一些:
public String inOrder {
return
(left != null ? left.inOrder() : "") +
content +
(right != null ? right.inOrder() : "");
}
现在每个内容字符串仅复制上面的节点数次(+1),这对于“通常”(非极不平衡)树来说要小得多。 (这种变体也很容易并行化。)
但事实上,StringBuilder版本通常是首选版本,因为它只复制每个内容字符串一次(当它附加到StringBuilder时),并且在内部调整大小时可能会多一些StringBuilder(如果你可以在实际转换之前估计最终大小,那么创建一个足够大的StringBuilder)。
答案 2 :(得分:2)
字符串在Java中是不可变的,当您向String添加内容时,会创建一个新对象。因此,在方法范围之外,这种变化是不可见的。
尝试使用StringBuilder而不是String:
public StringBuilder inOrder(StringBuilder string) {
if (left != null) left.inOrder(string);
string.append(content);
if (right != null) right.inOrder(string);
return string;
}
您可以在这里阅读:http://www.javaworld.com/javaqa/2000-05/03-qa-0526-pass.html以了解Java传递方法参数的方式以及为什么Strings immutability是原始代码中的问题。
此致 索林。
答案 3 :(得分:0)
Java是按值传递的。此方法无法更改对传递给方法的对象的引用。您可以更改对象的内容,但不能使用字符串,因为它们是不可变的(它们的内容不能更改)。
该行
string += content;
将新的String对象影响到字符串变量。它不会更改原始String对象的内容。
您需要将StringBuilder实例传递给您的方法,并附加到此StringBuilder:
public String inOrder() {
StringBuilder strinBuilder = new StringBuilder();
postOrder(stringBuilder);
return stringBuilder.toString();
}
private void postOrder(StringBuilder stringBuilder) {
if (left != null) left.postOrder(stringBuilder);
if (right != null) right.postOrder(stringBuilder);
}