循环拼接字符串必须用StringBuilder而非+号,因String不可变,+会频繁创建对象触发GC;StringBuilder通过可变数组和合理扩容策略提升性能,需循环外初始化、循环内append、最后toString()。

循环里拼字符串,别用+号,直接上StringBuilder——这是Java开发中最常见、也最容易见效的性能优化点。
为什么循环中必须用StringBuilder?
String对象不可变,每次用+拼接都会生成新对象。比如result += "item" + i,JVM实际会隐式创建StringBuilder→append→toString,循环1万次就可能产生上万个短命对象,触发频繁Young GC,拖慢系统。
StringBuilder内部维护可变字符数组,append只是往末尾追加,扩容策略为“旧容量×2+2”,没有中间对象开销。
标准写法三步走
- 循环外初始化:不要在for里new StringBuilder,避免重复创建
- 循环内只调append:支持String、int、boolean等类型,无需String.valueOf()装箱
- 循环结束后调一次toString():这是获取最终字符串的唯一出口,不能漏,也不能提前调
提升效率的关键细节
预估容量很实用:比如拼500条日志,每条平均60字符,可写new StringBuilder(500 * 60 + 1000),减少数组复制次数。
立即学习“Java免费学习笔记(深入)”;
处理分隔符更干净:不用每次判断是否首项,改用StringJoiner(Java 8+)或手动控制——全拼完再用deleteCharAt()删掉末尾多余符号。
需多次复用时,用sb.setLength(0)清空比新建实例更轻量,但要确保没其他引用指向它。
哪些情况其实不用StringBuilder?
- 单行拼接,如"User " + user.getName() + " logged in":编译器自动优化为StringBuilder,代码更清晰
- 拼接≤3次且内容简单:硬套StringBuilder反而增加冗余
- 多线程共享同一实例:绝对禁止!应每个线程独立创建,或改用StringBuffer(但有同步开销)


















