我们什么时候应该使用+来连接字符串,什么时候首选StringBuilder?何时适合使用concat。
我听说StringBuilder更适合循环中的连接。为什么会这样?
感谢。
答案 0 :(得分:45)
现代Java编译器通过StringBuilder的追加转换你的+操作。我的意思是说如果你做str = str1 + str2 + str3
,那么编译器将生成以下代码:
StringBuilder sb = new StringBuilder();
str = sb.append(str1).append(str2).append(str3).toString();
您可以使用DJ或Cavaj反编译代码来确认:) 所以现在使用+或StringBuilder更多是选择而不是性能优势:)
然而,考虑到编译器没有为您执行此操作的情况(如果您使用任何私有Java SDK来执行此操作,那么可能会发生这种情况),那么确定StringBuilder是最终避免大量不必要的方式{ {1}}对象。
答案 1 :(得分:31)
我倾向于在性能受到关注的代码路径上使用StringBuilder
。循环中重复的字符串连接通常是一个很好的选择。
首选StringBuilder
的原因是+
和concat
每次调用它们时都会创建一个新对象(前提是右侧参数不为空)。这可以很快加起来很多对象,几乎所有对象都是完全没必要的。
正如其他人所指出的,当你在同一个语句中多次使用+
时,编译器通常可以为你优化这个。但是,根据我的经验,当连接发生在单独的语句中时,此参数不适用。它肯定对循环没有帮助。
说完这一切之后,我认为最重要的应该是编写清晰的代码。有一些很好的分析工具可用于Java(我使用YourKit),这使得很容易找出性能瓶颈并优化它重要的位。
P.S。我从来不需要使用concat
。
答案 2 :(得分:15)
来自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;
上面的代码将构建99个新的
String
个对象,其中98个将被立即丢弃。创建新对象效率不高。<强>
StringBuffer
/StringBuilder
强>
StringBuffer
是可变的:当您想要修改内容时,请使用StringBuffer
或StringBuilder
。在Java 5中添加了StringBuilder
,它在所有方面都与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();
上面的代码只创建了两个新对象,即
StringBuffer
和返回的最终String
。StringBuffer
会根据需要进行扩展,但这样做会很昂贵,因此最好从一开始就使用正确的大小初始化StringBuffer
,如图所示。
答案 3 :(得分:5)
如果所有连接元素都是常量(例如:"these" + "are" + "constants"
),那么我更喜欢+,因为编译器会为你内联串联。否则,使用StringBuilder是最有效的方法。
如果对非常量使用+,编译器也将在内部使用StringBuilder,但调试变得很糟糕,因为使用的代码不再与源代码相同。
答案 4 :(得分:2)
我的建议如下:
+
:在连接2或3个字符串时使用,只是为了使代码简洁易读。StringBuilder
:在构建复杂的字符串输出时或在考虑性能时使用。String.format
:你没有在你的问题中提到这个,但它是我创建字符串的首选方法,因为它使代码在我看来最可读/最简洁,对日志语句特别有用。concat
:我认为我没有理由使用它。答案 5 :(得分:1)
如果您进行大量操作,请使用StringBuilder
。 通常循环是一个很好的指示。
这样做的原因是使用正常连接会产生大量中间String
对象,这些对象无法轻松“扩展”(即每个连接操作都会产生副本,需要内存和CPU时间)。另一方面,StringBuilder
只需要在某些情况下复制数据(在中间插入一些东西,或者因为结果变大而不得不调整大小),这样就可以节省那些复制操作。
使用concat()
与使用+
相比并没有什么好处(对于单个+
来说,它可能会稍微快一点,但是一旦你a.concat(b).concat(c)
,它实际上会是a + b + c
慢于{{1}})。
答案 6 :(得分:1)
编译器的性能增益适用于连接常量。 其余的用法实际上比直接使用StringBuilder慢。
使用“+”没有问题,例如用于为Exception创建消息,因为它不经常发生,并且应用程序已经在某种程度上已经被搞砸了。 避免在循环中使用“+”。
要创建有意义的消息或其他参数化字符串(例如Xpath表达式),请使用 String.format - 它的可读性要高得多。
答案 7 :(得分:1)
对单个语句使用+,对多个语句/循环使用StringBuilder。
答案 8 :(得分:1)
我建议使用concat进行两个字符串连接和StringBuilder,请参阅我对concatenation operator (+) vs concat()的解释