Java中的字符串连接 - 何时使用+,StringBuilder和concat

Man*_*ani 43 java string

什么时候我们应该使用+来连接字符串,什么时候首选StringBuilder?何时适合使用concat.

我听说StringBuilder更适合循环中的连接.为什么会这样?

谢谢.

Sau*_*abh 48

现代Java编译器通过StringBuilder的追加转换你的+操作.我的意思是说,如果你这样做str = str1 + str2 + str3,编译器将生成以下代码:

StringBuilder sb = new StringBuilder();
str = sb.append(str1).append(str2).append(str3).toString();
Run Code Online (Sandbox Code Playgroud)

您可以使用DJ或Cavaj对代码进行反编译来确认这一点:)所以现在使用+或StringBuilder更多的是选择而不是性能优势:)

但是考虑到编译器没有为您执行此操作的情况(如果您使用任何私有Java SDK来执行此操作,那么可能会发生这种情况),那么当您最终避免使用大量不必要的String对象时,必然会使用StringBuilder .

  • 是的,但如果在循环中使用`+`,运行时将为每次迭代创建一个新的`StringBuilder`,从而导致严重的性能损失. (12认同)

NPE*_*NPE 32

我倾向于StringBuilder在性能受到关注的代码路径上使用.循环内的重复字符串连接通常是一个很好的候选者.

喜欢的理由StringBuilder是,无论+concat创建新的对象每次调用时(提供的右手边参数不为空).这可以很快加起来很多对象,几乎所有对象都是完全没必要的.

正如其他人所指出的,当你+在同一个语句中多次使用时,编译器通常可以为你优化这个.但是,根据我的经验,当连接发生在单独的语句中时,此参数不适用.它肯定对循环没有帮助.

说完这一切之后,我认为最重要的应该是编写清晰的代码.有一些很棒的分析工具可用于Java(我使用YourKit),这使得很容易找出性能瓶颈并优化重要的位.

PS我从来不需要使用concat.

  • @shmosel有趣的是,在参考实现中, `str -> "foo" + str` 将是一个单例(非捕获 lambda 表达式),而 `"foo"::concat` 不会,因为运行时无法识别捕获的“String”实例是一个常量。 (2认同)

dim*_*902 17

来自Java/J2EE Job Interview Companion:

String

String是不可变的:您不能修改String对象,但可以通过创建新实例来替换它.创建新实例相当昂贵.

//Inefficient version using immutable String
String output = "Some text";
int count = 100;
for (int i = 0; i < count; i++) {
    output += i;
}
return output;
Run Code Online (Sandbox Code Playgroud)

上面的代码将构建99个新String对象,其中98个将立即被丢弃.创建新对象效率不高.

StringBuffer/StringBuilder

StringBuffer是可变的:使用StringBufferStringBuilder当你想修改内容时.StringBuilder在Java 5中添加了它,它在所有方面都是相同的,StringBuffer除了它不是同步的,这使得它更快,但代价是不是线程安全的.

//More efficient version using mutable StringBuffer
StringBuffer output = new StringBuffer(110);
output.append("Some text");
for (int i = 0; i < count; i++) {
  output.append(i);
}
return output.toString();
Run Code Online (Sandbox Code Playgroud)

上面的代码只创建了两个新对象,即返回StringBuffer的final String.StringBuffer根据需要扩展,但这是昂贵的,因此最好StringBuffer从一开始就用正确的大小初始化,如图所示.


Sea*_*oyd 6

如果所有连接元素都是常量(例如:) "these" + "are" + "constants",那么我更喜欢+,因为编译器会为你内联连接.否则,使用StringBuilder是最有效的方法.

如果对非常量使用+,编译器也将在内部使用StringBuilder,但调试变得很糟糕,因为使用的代码不再与源代码相同.


Ada*_*ski 5

我的建议如下:

  • +:在连接 2 或 3 个字符串时使用,只是为了保持代码简洁和可读。
  • StringBuilder:在构建复杂的字符串输出或关注性能时使用。
  • String.format:您在问题中没有提到这一点,但这是我创建字符串的首选方法,因为在我看来,它使代码最具可读性/简洁性,并且对于日志语句特别有用。
  • concat:我认为我没有理由使用这个。