StringBuilder 拼接长文本更高效,因 String 不可变,每次“+”都生成新对象并丢弃旧对象,导致大量临时对象和垃圾回收压力;StringBuilder 则在可变数组上追加,复用内存。

用 StringBuilder 替代 String 拼接长文本,核心在于避免创建大量中间 String 对象——因为 String 不可变,每次 + 都会生成新对象,而 StringBuilder 在内部可变数组上追加,复用同一块内存。
为什么 String 拼接会产生大量垃圾?
Java 中 String 是不可变的。例如:
String s = "a" + "b" + "c" + "d"; // 编译期优化为常量,无问题
但运行时拼接(尤其循环中)就不同:
String result = "";
for (int i = 0; i < 1000; i++) {
result += "item" + i; // 每次都 new String(),前 999 个立即成垃圾
}这会在堆中产生约 1000 个短命 String 对象,触发频繁 GC,拖慢性能。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
StringBuilder 的正确用法(关键细节)
不是只要用了 StringBuilder 就一定高效,要注意初始化容量和复用方式:
-
预设足够初始容量:避免内部数组多次扩容(扩容需复制旧数组)。例如拼接 1000 个平均长度 20 的字符串,可设
new StringBuilder(20_000) -
复用实例,避免反复 new:在方法内创建后及时
.setLength(0)重置,比每次新建更轻量 -
链式调用优先:用
append()连续追加,不要拆成多行再 toString() —— 每次toString()都会生成新String,但只在最终需要时调用一次即可
典型优化对比示例
❌ 低效写法(隐式 StringBuilder + 无容量预设):
String buildLog(List<String> lines) {
String log = "";
for (String line : lines) {
log += "[" + System.currentTimeMillis() + "] " + line + "\n"; // 多次装箱、字符串连接、对象创建
}
return log;
}✅ 高效写法(显式控制、预估容量、复用):
String buildLog(List<String> lines) {
// 预估总长:每行约 30 字符 × 行数 + 留余量
int estimatedLen = lines.size() * 40;
StringBuilder sb = new StringBuilder(estimatedLen);
long now = System.currentTimeMillis(); // 提前获取,避免循环内重复调用
for (String line : lines) {
sb.append('[').append(now).append("] ").append(line).append('\n');
}
return sb.toString(); // 只调用一次
}什么情况不用 StringBuilder?
并不是所有拼接都要改。以下场景无需强行替换:
- 拼接项极少(如固定 2~3 个字面量),JVM 会自动优化为
StringBuilder或直接常量折叠 - 使用
String.join()或MessageFormat等语义更清晰的工具,且性能满足要求 - 单次拼接、生命周期短、GC 压力不敏感(如日志调试语句)
关键不在“用没用 StringBuilder”,而在是否理解字符串不可变性带来的开销,并根据数据规模、执行频率和内存敏感度做合理选择。

















