StringBuilder适合单线程下频繁修改字符串的场景,如循环拼接、SQL构建、JSON生成、日志组装;其高效源于可变数组、无同步开销和可控扩容;不适用于多线程共享或仅少量拼接。

StringBuilder适合在单线程环境下频繁修改字符串的场景,比如循环拼接、SQL构建、JSON生成、日志组装等。它不适用于多线程共享修改,也不适合只读或极少变动的字符串。
适合StringBuilder的典型场景
这些情况都满足两个关键条件:字符串要反复改动 + 执行环境是单线程。
-
循环内字符串拼接:比如遍历集合生成逗号分隔的ID列表,用
+=拼String会创建上万对象,而StringBuilder复用同一块内存。 - 动态SQL语句构造:WHERE条件不确定,需逐段追加字段和参数,避免字符串重复拷贝。
-
JSON或XML内容组装:键值对数量不定,通过
append逐步写入,比String叠加更轻量。 -
日志消息格式化:如
sb.append("user=").append(id).append(", action=").append(op),无锁、低开销。
StringBuilder的性能特点
它的高效不是凭空来的,核心来自三方面设计:
-
内部字符数组可变:底层是
char[](JDK 9+为byte[]),所有操作(append、insert、delete)都在原数组上完成,不新建对象。 -
无同步开销:方法没加
synchronized,没有线程安全机制,单线程下比StringBuffer快10%–15%左右。 -
容量自动扩容但可控:默认初始容量16,超出时按
oldCapacity * 2 + 2扩容;可预估长度传入构造参数(如new StringBuilder(1024)),减少扩容次数。
什么时候不该用StringBuilder
选错类型反而拖慢程序,注意避开这些坑:
立即学习“Java免费学习笔记(深入)”;
-
仅一次拼接或少量操作:如
"Hello" + name + "!",编译器会自动优化成StringBuilder,手动写反而啰嗦。 -
多线程共用同一个实例:多个线程同时调用
append可能造成数据错乱,此时应改用StringBuffer,或用局部变量隔离。 - 字符串基本不变:如配置项、常量、Map的key,String的不可变性和常量池更合适,也更安全。
简单对比:String vs StringBuffer vs StringBuilder
三者本质区别就两点:是否可变、是否线程安全。
- String:不可变 + 线程安全 → 适合固定文本、共享引用、做hash key。
- StringBuffer:可变 + 线程安全 → 多线程拼接,但同步带来开销,日常少用。
- StringBuilder:可变 + 非线程安全 → 单线程高频修改的首选,平衡了性能与易用性。











