应使用stringbuilder替代循环内字符串拼接:循环外创建一次、预估容量初始化、仅末尾调用tostring();编译期常量、单次少量拼接、string.join及日志占位符等场景无需手动优化。

直接在循环体内用 + 拼接字符串,会因 String 不可变性触发频繁对象创建和内存复制,时间复杂度升至 O(n²),GC 压力陡增。核心解法是改用 StringBuilder,并注意初始化与复用方式。
必须用 StringBuilder 替代 +=
每次 result += "xxx" 在循环中,JVM 实际执行的是:
→ 新建一个 StringBuilder
→ append 旧内容和新内容
→ toString() 生成新 String
→ 丢弃中间对象
10 万次循环可能产生 10 万个临时 StringBuilder 和 String 对象。
- ✅ 正确做法:在循环外创建一次
StringBuilder,循环内只调用.append() - ❌ 错误写法:
String s = ""; for (...) { s += "a"; }—— 每轮都新建对象
预估容量,减少数组扩容
StringBuilder 内部用 char[](Java 9+ 是 byte[])存储,初始容量默认为 16。若拼接结果远超该值,会触发自动扩容(通常翻倍),每次扩容都要复制原数组,带来额外开销。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 若能粗略估算最终长度(如拼接 10000 个 "item123",每个约 8 字符 → 总长 ≈ 80000),就显式指定:
new StringBuilder(80000) - 不确定时,宁可略大勿小;过度预留(如设 1MB)影响极小,但反复扩容代价明确
避免在循环里反复 toString()
如果在每次迭代中都调用 sb.toString(),等于又回到“每轮造一个新 String”的老路,完全丧失优化意义。
- 只在循环结束后调用一次
.toString() - 若需中间结果做判断(如截断、条件终止),应改用
sb.length()、sb.charAt()等直接操作方法,不转 String
区分场景,不盲目优化
不是所有拼接都要手动换 StringBuilder:
- 编译期常量拼接(如
"a" + "b" + "c")会被 javac 直接优化成字面量,无需干预 - 单次拼接少量变量(如
return prefix + value + suffix),JVM 通常已自动转为 StringBuilder,不用改 - 集合转字符串且带分隔符,优先用
String.join(",", list),它内部已优化,语义更清晰 - 日志拼接(如
log.info("id=" + id))即使日志关闭也会执行拼接 → 改用占位符:log.info("id={}", id)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










