【发布时间】:2012-08-10 03:48:05
【问题描述】:
可能重复:
StringBuilder vs String concatenation in toString() in Java
我想知道,由于编译器在执行字符串连接时在内部使用 StringBuilder 来附加字符串,那么如果字符串连接已经为您完成了这项工作,那么有什么意义?为什么还要使用 StringBuilder 呢?还有其他具体原因吗?
【问题讨论】:
标签: java stringbuilder
可能重复:
StringBuilder vs String concatenation in toString() in Java
我想知道,由于编译器在执行字符串连接时在内部使用 StringBuilder 来附加字符串,那么如果字符串连接已经为您完成了这项工作,那么有什么意义?为什么还要使用 StringBuilder 呢?还有其他具体原因吗?
【问题讨论】:
标签: java stringbuilder
正如您所提到的,您不应使用StringBuilder 而不是简单的字符串连接表达式,例如a + " = " + b。后者打字速度更快,更容易阅读,而且编译器无论如何都会在内部使用StringBuilder,因此重写它并没有性能优势。
但是,如果您在循环中连接大量字符串,StringBuilder 会很有用。以下代码效率低下。它需要 O(n2) 时间来运行并创建许多临时字符串。
String result = "";
for (int i = 0; i < foo.length; ++i)
{
result += bar(foo[i]); // Bad
}
试试这个:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < foo.length; ++i)
{
sb.append(bar(foo[i]));
}
String result = sb.toString();
编译器只优化简单的a + b + c 表达式。无法自动优化上述代码。
【讨论】:
result += bar(foo[i]) 将产生类似(假设javac)result = new StringBuilder().append(result).append(foo[i]).toString() 的代码。请注意,这比使用 StringBuilder 要多得多。
result 时都会创建一个新字符串。
+= 将在每次迭代中创建一个新的StringBuilder,复制源字符串,附加您要连接的任何内容(这也可能需要一个副本),然后将其转换为String(这是另一个副本)。使用一个StringBuilder 可以避免不必要的复制。
您在哪里假设字符串连接在内部使用 stringbuilder ?也许一个简单的 concat 会被优化掉,但这绝对不会:
String s = "";
for (int i = 0; i < 1000; i++){
for (int j = 0; j < 1000; j++){
s+= "" + i + j
}
}
【讨论】:
s = new StringBuilder.append("").append(i).append(j).toString(); 假设编译器是 javac。
s字符串中复制了所有的字符,只有then 附加 i 和 j。每个循环,您都在复制您之前拥有的所有字符(它们本身是从之前的循环中复制的),从而为您提供 O(n^2) 性能。通过从循环体中删除新的 StringBuilder,您可以消除所有多余的复制。