绝大多数情况下循环内多次拼接选StringBuilder,单次固定拼接用String更简洁无性能损失;StringBuilder初始化容量影响扩容次数,预估长度可设为256或N×L×1.2;其线程不安全,多线程需用StringBuffer或ThreadLocal;String.concat()两两拼接更快但不支持链式,而a+b+c在非常量时JVM仍生成StringBuilder。

字符串拼接场景下,用 StringBuilder 还是 String?
绝大多数情况下,循环内或多次拼接选 StringBuilder;单次、固定拼接(如 "a" + "b" + "c")用 String 更简洁且无性能损失。Java 编译器会把常量字符串加法在编译期优化为一个字面量,运行时根本不会创建中间对象。
StringBuilder 的初始化容量为什么重要?
默认构造的 StringBuilder() 内部字符数组初始容量是 16。一旦追加内容超过该长度,就会触发数组扩容(通常是当前容量 × 2 + 2),涉及内存分配和数组复制。高频拼接时,提前预估长度能避免多次扩容。
- 已知最终长度约 200 字符 → 用
new StringBuilder(256) - 拼接 N 个字符串,平均长度 L → 初始容量设为
N * L * 1.2左右较稳妥 - 不确定长度但确定不会太小 → 至少设为
64或128,比默认 16 更实用
为什么不能在多线程里共享未同步的 StringBuilder?
StringBuilder 是线程不安全的:它的 append、insert 等方法不加锁,多个线程同时调用可能破坏内部 char[] 和 count 值,导致数据丢失、越界异常甚至静默错误(比如拼出乱序或截断的字符串)。
- 需要多线程拼接 → 改用
StringBuffer(方法带synchronized) - 每个线程各自拼接 → 每个线程 new 自己的
StringBuilder实例,完全没问题 - 用线程局部变量 →
ThreadLocal可复用又免同步,但要注意及时remove()防内存泄漏
String.concat() 和 StringBuilder.append() 性能差多少?
对两个字符串拼接,String.concat() 通常比 StringBuilder.append().toString() 快一点(少一次对象创建和数组拷贝),但它只接受单个 String 参数,不支持链式调用,也不适用于 >2 次拼接场景。
立即学习“Java免费学习笔记(深入)”;
String a = "hello"; String b = "world"; String c = "!"; // ✅ 两两拼接快:底层直接 new char[] 并 copy String s1 = a.concat(b).concat(c);// ✅ 多次拼接稳:可链式、可预设容量 StringBuilder sb = new StringBuilder(32); sb.append(a).append(b).append(c); String s2 = sb.toString();
真正容易被忽略的是:哪怕只拼三次,如果写成 a + b + c(非编译期常量),JVM 仍会悄悄生成一个 StringBuilder —— 所以别迷信“+ 简单就一定慢”,要看是否在循环里重复执行。










