StringBuilder 比 String 更适合频繁修改,因为 String 不可变、每次拼接都生成新对象,而 StringBuilder 可变、在原数组上操作,减少对象创建和 GC 压力;预估容量可避免频繁扩容;复用实例并合理使用 API(如 append、setLength)能进一步提升性能。

直接用 StringBuilder 替代 String 进行频繁拼接或修改,能避免创建大量中间字符串对象,显著减少内存分配和 GC 压力。
为什么 StringBuilder 比 String 更适合频繁修改
String 是不可变的,每次拼接(如 + 或 concat())都会生成新对象;而 StringBuilder 是可变的字符序列,内部用 char 数组存储,所有修改都在原数组上进行。比如循环拼接 1000 次字符串,用 String 会创建约 1000 个临时对象,用 StringBuilder 只需 1 个实例 + 若干数组扩容(通常最多几次)。
初始化时预估容量,减少数组扩容
StringBuilder 默认初始容量是 16,当内容超出时会自动扩容(通常是当前容量 * 2 + 2)。频繁扩容会复制数组,影响性能。如果能预估最终长度,建议显式指定容量:
- new StringBuilder(1024) —— 适用于已知大致长度的场景,如拼接日志、JSON 片段
- 若不确定,可用 ensureCapacity(int minCapacity) 在关键节点预留空间
- 避免过度预留(如设为 100000 却只用 200),浪费堆内存
复用实例,避免重复创建
在循环或高频调用中,不要每次 new 一个 StringBuilder。推荐方式:
立即学习“Java免费学习笔记(深入)”;
- 方法内局部变量:如果单次调用中完成全部拼接,直接 new 并使用,作用域结束即丢弃
- 线程内复用:在 ThreadLocal 中缓存 StringBuilder 实例,适合高并发但每线程操作独立的场景
- 避免跨线程共享:StringBuilder 不是线程安全的,多线程共用必须加锁,此时不如用 StringBuffer(但性能更低)
选择合适的方法,减少无效操作
注意 API 使用细节,避免隐式低效行为:
- 用 append() 代替 insert(0, ...) 做前插——后者需移动后续所有字符
- 清空内容时用 setLength(0),比 new StringBuilder() 更轻量
- 需要转成字符串时再调用 toString(),不要过早转换打断链式操作
- 拼接少量固定字符串(如 2~3 个),JVM 会自动优化为 StringBuilder,无需手动干预


















