应使用StringBuilder替代+拼接字符串,循环前创建并预估容量,循环中append、结束后toString;避免每轮新建或循环内反复调用toString。

在循环中用 + 拼接字符串,会频繁创建 String 对象,因为 String 不可变,每次拼接都生成新对象,导致内存压力大、GC 频繁、性能下降。核心解法是改用可变的字符串容器——StringBuilder(单线程)或 StringBuffer(多线程,带同步开销,一般不用)。
用 StringBuilder 替代 + 拼接
在已知循环次数或数据量较大时,优先初始化 StringBuilder 并预估容量,避免内部数组多次扩容:
- 不指定容量:默认 16 字符,扩容规则为
oldCapacity * 2 + 2,可能触发多次Arrays.copyOf - 推荐显式指定初始容量,例如:
new StringBuilder(estimatedLength),估算依据可为:各字段平均长度 × 循环次数 + 分隔符长度 × (次数−1) - 循环内调用
append(),最后调用toString()获取结果
避免在循环外重复创建 StringBuilder
不要写成“每轮 new 一个 StringBuilder”,这仍会产生大量临时对象:
- ❌ 错误示范:
for (...) { String s = new StringBuilder().append(...).toString(); } - ✅ 正确做法:循环前创建一次,循环中持续
append(),循环结束后统一toString()
注意 toString() 的时机和复用
StringBuilder.toString() 每次都新建 String 对象,所以不要在循环中反复调用它来获取中间结果;如需中间字符串,应仅在真正需要时调用一次。若需多次生成不同拼接结果,考虑提取方法封装逻辑,而非复用同一实例未重置。
- 必要时调用
setLength(0)重置内容(比新建更轻量),但要注意引用安全(避免其他地方还持有该实例) - 不建议在多线程间共享同一
StringBuilder实例,除非加锁或明确限定作用域
特殊场景:少量固定拼接可用 String.join 或 Text Blocks
如果循环实际只执行 2~3 次,或数据来自集合且结构规整,可考虑更简洁、安全的替代方式:
-
String.join(",", list):适合集合元素转字符串,底层也用StringBuilder,但封装好、不易出错 - JDK 15+ 可配合
String.formatted()或文本块 +stripIndent()处理模板化拼接 - 编译期常量拼接(如
"a" + "b" + "c")由编译器优化为单个字符串字面量,无需干预
















