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

Soy*_*yuz 46 java string stringbuilder concatenation append

这个答案中,它说(暗示)无论如何都将String连接优化为StringBuilder操作,所以当我编写代码时,是否有任何理由在源代码中编写StringBuilder代码?请注意,我的用例与OP的问题不同,因为我连接/追加数十万行.

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

Tom*_*ann 112

我认为StringBuildervs 的使用+实际上取决于你使用它的上下文.

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

String one = "abc";
String two = "xyz";
String three = one + two;
Run Code Online (Sandbox Code Playgroud)

这将编译String three为:

String three = new StringBuilder().append(one).append(two).toString();
Run Code Online (Sandbox Code Playgroud)

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

String out = "";
for( int i = 0; i < 10000 ; i++ ) {
    out = out + i;
}
return out;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

您需要仔细查看需要手动应用的位置,StringBuilder并尝试使用它,这样也不会降低代码的可读性.

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

  • 您的反编译代码(在第二个for循环中)是实际反编译的输出,或者这是您的猜测?如果你调试一个带有"+"字符串连接的for/while循环,你会发现StringBuilder对象没有在每个循环中重新创建,但事实上同一个循环被重用.否则,如果您要替换较重的对象(即StringBuilder for String),您真正获得了哪些优化? (3认同)
  • 我也想知道@SpencerKormos问题的答案.编译器是否为每个循环迭代实际创建了一个新的`StringBuilder`?为什么这是最佳的? (2认同)