我在想,既然编译器在执行字符串拼接时内部使用了 StringBuilder,那么使用 StringBuilder 还有什么意义呢?如果字符串拼接已经完成了任务,为什么还要费心使用 StringBuilder?是否还有其他特定原因?此外,这篇文章 StringBuilder vs String concatenation in toString() in Java 与此话题重复,请注意。
正如您提到的那样,您不应该使用 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
表达式。它无法自动优化上述代码。
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();
- obatakus
字符串复制所有字符,只有然后附加i
和j
。每次循环,您都会复制先前拥有的所有字符(它们本身已从先前的循环中复制),从而获得O(n ^ 2)性能。通过从循环体中删除新的StringBuilder,可以消除所有冗余的复制。 - yshavit
result += bar(foo[i])
会生成类似以下代码(假设是 javac):result = new StringBuilder().append(result).append(foo[i]).toString()
。请注意,这比使用一个StringBuilder
要繁琐得多。 - obataku+=
操作符会在每次迭代时创建一个新的StringBuilder
对象,将源字符串复制一份,再连接你要添加的内容(这也可能需要一次复制),最后将其转换为一个String
(另一次复制)。使用一个StringBuilder
对象可以避免不必要的复制。 - obataku