Java:String concat vs StringBuilder - 已经过优化,所以我该怎么办?

时间:2013-02-18 00:03:44

标签: java string append concatenation stringbuilder

this answer中,它表示(暗示)字符串连接无论如何都被优化为StringBuilder操作,因此当我编写代码时,是否有任何理由在源代码中编写StringBuilder代码?请注意,我的用例与OP的问题不同,因为我连接/追加数十万行。

让自己更清楚:我很清楚每个人的差异,只是我不知道是否值得实际编写StringBuilder代码,因为它的可读性较差,而且当它的表兄弟比较慢时,String类是无论如何,在编译过程中自动转换。

4 个答案:

答案 0 :(得分:111)

我认为使用StringBuilder vs +实际上取决于您使用它的上下文。

通常使用JDK 1.6及更高版本,编译器将使用StringBuilder自动将字符串连接在一起。

String one = "abc";
String two = "xyz";
String three = one + two;

这会将String three编译为:

String three = new StringBuilder().append(one).append(two).toString();

这非常有用,可以节省一些运行时间。然而,这个过程并不总是最佳的。举个例子:

String out = "";
for( int i = 0; i < 10000 ; i++ ) {
    out = out + i;
}
return out;

如果我们编译为字节码然后反编译生成的字节码,我们得到类似的东西:

String out = "";
for( int i = 0; i < 10000; i++ ) {
    out = new StringBuilder().append(out).append(i).toString();
}
return out;

编译器优化了内部循环,但肯定没有做出最好的优化。为了改进我们的代码,我们可以使用:

StringBuilder out = new StringBuilder();
for( int i = 0 ; i < 10000; i++ ) {
    out.append(i);
}
return out.toString();

现在这比编译器生成的代码更优化,因此在需要高效代码的情况下,肯定需要使用StringBuilder / StringBuffer类编写代码。当前的编译器在处理循环中的串联字符串方面不是很好,但是将来可能会改变。

您需要仔细查看需要手动应用StringBuilder的位置,并尝试在不降低代码可读性的地方使用它。

注意:我使用JDK 1.6编译代码,并使用javap程序反编译代码,该程序吐出字节代码。它很容易解释,并且在尝试优化代码时通常是一个有用的参考。编译器会在幕后更改您的代码,因此查看它的作用总是很有趣!

答案 1 :(得分:3)

你问题中的关键词是“据说更慢”。你需要确定这是否确实是一个瓶颈,然后看看哪个更快。

如果您要编写此代码,但尚未编写代码,请编写更清楚的内容,然后在必要时查看是否为瓶颈。

虽然使用你认为更快的代码是有意义的,但如果两者都具有相同的可读性,那么实际上花时间找出哪些代码在你没有需要时更快就是浪费时间。可读性高于性能,直到性能不可接受。

答案 2 :(得分:2)

这取决于具体情况,但StringBuilder被认为有点快。如果你在循环中进行连接,那么我建议你使用StringBuilder。

无论如何,我会建议你对代码进行分析和基准测试(如果你做了如此大规模的追加)。

请注意:StringBuilder的实例是可变的,不能在线程之间共享(除非你真的知道你在做什么。)而不是String是不可变的。

答案 3 :(得分:0)

我可能会误解你的问题,但在添加字符串时StringBuilder会更快。所以,是的,如果你要追加“数十万行”,你肯定应该使用StringBuilder(或者如果你运行的是多线程应用程序,则使用StringBuffer)。

(评论中更全面的答案)