过去,我一直认为在构建包含变量的字符串时应使用StringBuilder
和append(String)
,而不是string += split[i]
。在什么情况下这是准确的?我问,因为通常,如果我要写下面的内容:
String[] split = args; // command line arguments or whatever
String myString = "";
for (int i = 0; i < split.length; i++) {
myString += split[i];
}
我的IDE告诉我应该转换为使用StringBuilder。但是,写下这样的东西:
StringBuilder build = new StringBuilder();
build.append("the ").append(build.toString()).append(" is bad").append(randomvar);
build.toString();
当我应该使用String时,IntelliJ实际上使用StringBuilder列为性能问题。它被列为性能问题这一事实表明它实际上可能会导致问题,而不是只是稍微慢一点。
我注意到第一个例子是一个循环,第二个例子是没有 - 是一个建议用于大量连接的StringBuilder但是正常连接对于非循环情况更好(这也意味着在一个循环中运算符{会使用{1}},而在循环之外它可能是+=
- 是+ =问题而不是+?)
答案 0 :(得分:9)
字符串连接在后台转换为对StringBuilder.append()的调用。
字符串文字串联(或至少可以)转换为单个字符串文字。
你可能在循环中使用了一个String变量(不仅仅是两个文字),因此Java不能用文字替换它;它必须使用StringBuilder。这就是为什么在循环中进行String连接应该使用单个StringBuilder完成的原因,否则Java会在每次循环迭代时最终创建另一个StringBuilder实例。
另一方面,这样的事情:
String animals = "cats " + "dogs " + "lizards ";
使用单个字符串文字将(或可以)替换(由Java,而不是您),因此使用StringBuilder实际上会适得其反。
答案 1 :(得分:3)
从java 1.5开始,String +运算符被转换为对StringBuilder的调用。
在你的例子中,循环应该更慢,因为+运算符每次循环都会创建一个新的StringBuilder实例。
答案 2 :(得分:1)
编译器实际上会在编译之前将它们都转换为相同的形式,因此两者都不会导致任何性能差异。在这种情况下,您希望使用最短且最易读的方法。
“实现可以选择执行转换和连接 在一步中避免创建然后丢弃中间体 字符串对象。增加重复字符串的性能 连接,Java编译器可以使用StringBuffer类或a 类似的技术减少了中间String对象的数量 通过评估表达式创建的。
对于原始类型,实现也可以优化掉 通过直接从基元转换来创建包装器对象 键入字符串。“
来源:http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#15.18.1.2
答案 3 :(得分:0)
对于小的concats,你可以使用+运算符,没有问题。当我们要连接大字符串时会指示StringBuffer,因此使用此类可以节省内存和处理器的时间。
您可以尝试使用+运算符连接100万个单词,并使用StringBuffer运行相同的teste,以便自己查看不同的单词。