字符串连接,然后循环追加

String Concatenation and then append in a loop

从 Bruce Eckel 所著的 "Thinking in Java" 一书中找到了这段摘录。

If you try to take shortcuts and do something like append(a + ": " + c) , the compiler will jump in and start making more StringBuilder objects again.

这是否意味着我们不应该用一行代码替换一组追加操作;例如 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?

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

At the point where you're concatenating in a loop - that's usually when the compiler can't substitute StringBuilder by itself.

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

这不是编译器会有效地为您执行的优化。从文体上来说,我会这样写。

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

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

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

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

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

基本上,编译器用 StringBuilder 替换 String 连接的实例,所以你的行

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

改为

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

如您所见,它只是创建了 另一个 StringBuilder,这是多余的,因为您已经有了一个。最重要的是,它需要在循环的 每次 迭代中这样做,导致大量创建和垃圾收集无用。

所以是的,直接附加到您已经拥有的 StringBuilder 肯定会更好,而不是连接。是否以单行流利的方式执行此操作主要是个人喜好问题。

我不确定您找到的 "can't substitute StringBuilder" 答案是什么意思。他们可能意味着它不会重复使用您现有的构建器(而是创建一个新的构建器)。

这对 Java 8 仍然有效,尽管从那以后有其他流媒体方法,就像其他答案之一显示的那样。