「字符串拼接不要用 +,用 StringBuilder」几乎是每个 Java 面试题必备。但理想要结合场景,下面把两者掰开讲清楚。

一、为什么 "+" 在循环里慢

先看一段常见代码:

String result = "";
for (int i = 0; i < 10000; i++) {
    result += i; // 在循环里用 + 拼接
}

Java 中 String 是不可变对象。每次 result += i 都会创建一个新的字符串对象,意味着:

  • 每次循环都要把旧字符串的内容全部复制一遍;
  • 循环 N 次,时间复杂度退化到 O(N²),并产生大量等待 GC 的临时对象。

注意:编译器可能把 + 优化为 StringBuilder,但循环体内部每次迭代都会 new 一个新的 StringBuilder,性能开销依然明显。

二、正确姿势:StringBuilder

把 StringBuilder 放在循环外面,复用同一个对象:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.append(i);
}
String result = sb.toString();

单线程场景推荐 StringBuilder;如果涉及多线程并发拼接,才考虑线程安全的 StringBuffer。

三、其他常量拼接场景

不是所有地方都要用 StringBuilder。经验原则:

  • 拼接少量常量字符串(一行内):直接使用 + 即可,可读性更好,编译器会做优化,无需刻意换成 StringBuilder。
  • 循环内大量拼接:必须使用循环外的 StringBuilder。
  • 格式化文本:优先使用 String.format 或占位符模板,代码更清晰。

四、小结

性能优化的前提是先确认瓶颈。字符串拼接造成的问题通常出现在「循环 + 大字符串」组合下,其它场景不必过度优化。