循环中拼接字符串应复用stringbuilder:循环外初始化、预设合理容量、用setlength(0)清空重用,避免循环内new和tostring(),防止频繁gc。

在循环中拼接字符串时,避免 StringBuilder 重复创建对象的关键是“复用 + 预估 + 控制生命周期”。不是用了 StringBuilder 就自动优化,写法不当照样产生大量临时对象、触发频繁 GC。
循环外初始化,循环内复用
每次在循环体内 new StringBuilder(),等于每轮都分配新数组、重置计数器、浪费默认容量(16),完全抵消其优势。必须把实例声明和创建提到循环之前。
- ✅ 正确:在方法开头或 for 循环前创建一次,全程 append,最后 toString()
- ❌ 错误:for (String s : list) { StringBuilder sb = new StringBuilder(); ... }
预设合理初始容量,减少扩容复制
扩容会调用 System.arraycopy 复制整个已有内容,开销是 O(n)。拼接前若能估算总长度,就显式传入容量参数,避免多次翻倍扩容(oldCapacity × 2 + 2)。
- 例如拼接 10000 条日志,每条平均 64 字符 → 初始容量设为 640000,再加 10% 余量更稳妥
- 无法精确估算时,用 Math.max(estimated, 512) 或直接设为 4096,比默认 16 更可靠
- 运行时可调用 sb.ensureCapacity(minCapacity) 主动预留,只在不足时生效
清空重用比新建更轻量
如果需在单次任务中多次拼接(如生成多行 CSV、批量 SQL),推荐复用同一实例,并用 sb.setLength(0) 清空内容。
- setLength(0) 不释放底层数组,不触发 GC,只重置内部计数器,比 new StringBuilder() 快得多
- 注意:不能跨线程共享;清空前确保无其他引用持有该实例,防止脏数据
禁止循环内调用 toString()
toString() 是“快照”操作,会完整复制当前 char[] 生成新 String。在循环里反复调用,等于每轮都制造一个完整字符串对象,彻底白费 StringBuilder 的设计初衷。
- 只在所有 append 完成后调用一次 sb.toString()
- 调试时可用 sb.length() 或 sb.substring(0, Math.min(50, sb.length())) 查看片段,不触发全量复制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











