字符串串联,然后附加在循环中

时间:2018-09-03 06:34:52

标签: java string performance concatenation stringbuilder

从布鲁斯·埃克尔(Bruce Eckel)撰写的“ Java中的思想”一书中找到了节选。

  

如果您尝试采取捷径并执行类似append(a + ": " + c)的操作   ,编译器将进入并开始制作更多 StringBuilder   再次物体。

这是否意味着我们不应该用一行代码替换一组追加操作;例如result.append(i + ": " + 2*i + " ")

StringBuilder result = new StringBuilder();
for(int i = 0; i < 25; i++) {
    result.append(i);
    result.append(": ");
    result.append(2*i);
    result.append(", ") 
}

上面的语句对于Java 8也适用吗?

answer摘录于SO :(让我更加困惑)

  

在您将串联在一起时,通常是   当编译器无法单独替换 StringBuilder时。

也欢迎与首选编码风格有关的任何方面。

3 个答案:

答案 0 :(得分:3)

这不是编译器将为您高效完成的优化。从风格上讲,我会这样写。

StringBuilder result = new StringBuilder();
for (int i = 0; i < 25; i++) {
    result.append(i).append(": ").append(2 * i).append(", ");
}

注意:IDE(如IntelliJ)将检测到并提供自动修复,因为它是常见的翻译。

答案 1 :(得分:2)

基本上,编译器将String的串联实例替换为StringBuilder,因此您的代码行

result.append(i + ": " + 2*i + " ");

已更改为

result.append(new StringBuilder().append(i).append(": ").append(2*i).append(" ").toString());

就像您看到的那样,它只是创建另一个 StringBuilder,因为您已经有一个,所以这是多余的。最重要的是,它需要在循环的每次迭代中执行此操作,从而导致大量的创建和垃圾回收。

所以是的,最好直接附加到您已经拥有的StringBuilder上,而不是进行串联。是否在单个流水线中执行此操作主要取决于偏好。

我不确定您找到的答案“不能替代StringBuilder”意味着什么。他们可能意味着它不会再使用您现有的构建器(而是创建一个新的构建器)。

这对于Java 8仍然有效,尽管从那时起,还有其他流方法,就像其他答案之一所示。

答案 2 :(得分:0)

是的,当性能至关重要时,我们仍然应该使用链式附加而不是字符串连接。

但是,每当性能不重要时,我们都应努力提高代码的可读性,清晰度和重用性。因此,我的风格选择是:

IntStream
    .range(0, 25)
    .map(i, String.format("%d: %d", i, i*2)
    .collect(Collectors.joining(", "));