StringBuilder性能优化关键在容量控制:初始化时预估并指定容量可避免频繁扩容(新容量=旧容量×2+1),减少内存分配与GC压力;toString()前应调用trimToSize()收缩底层数组,节省内存拷贝。

用 StringBuilder 做字符串拼接,不是“用了就快”,关键在怎么用——尤其是容量控制和初始化方式,直接影响内存分配次数和GC压力。
初始化时预估容量,避免频繁扩容
StringBuilder 默认容量是16,一旦追加内容超出,就会触发扩容:新容量 = 旧容量 × 2 + 1(JDK 1.8+)。反复扩容意味着多次数组复制、内存重分配,拖慢性能。
- 如果能预估最终长度(比如拼接100个平均长度为20的字符串),直接 new StringBuilder(2000) 更高效
- 日志拼接、SQL构建、JSON组装等固定模式场景,建议显式指定初始容量
- 不确定长度但有上限时,宁可略高估(如设为512),也比连续扩容更划算
慎用 toString() 前的冗余操作
toString() 会基于当前 length 创建新 String 对象,但若 StringBuilder 内部 char[](或 byte[])远大于实际字符数,会浪费内存拷贝。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 避免先 append 大量内容,再 delete 或 replace 掉大部分——此时 capacity 不变,但实际 length 很小,toString() 仍要复制整个底层数组
- 必要时可调用 trimToSize(),让底层数组收缩到当前 length,节省后续 toString() 的内存开销
- 注意:trimToSize() 本身也有开销,仅在 length 比 capacity 小很多(如
单线程场景下,优先用 StringBuilder 而非 StringBuffer
StringBuffer 所有方法都加了 synchronized,带来明显同步开销;而 StringBuilder 在绝大多数业务逻辑(如 Controller 层组装响应、Service 层构建参数)中是单线程使用的。
立即学习“Java免费学习笔记(深入)”;
- 压测数据显示:JDK 17 下,10 万次拼接,StringBuilder 耗时约 12ms,StringBuffer 约 28ms
- 若需多线程共享拼接对象,推荐 ThreadLocal<StringBuilder>,比 StringBuffer 更轻量、无锁
- JDK 14+ 引入 ConcurrentStringBuilder,但目前生态支持有限,生产环境仍建议优先用 ThreadLocal 方案
结合 JDK 9+ 字符串优化,减少 Latin-1 编码开销
JDK 9 起 String 改用 byte[] + coder 字段,对纯 ASCII 字符串(如数字、英文标识符、HTTP header)自动启用 Latin-1 编码,内存减半。StringBuilder 底层也适配此机制。
- 拼接内容以 ASCII 为主时(如 "user_id=123&status=active"),StringBuilder 的底层 byte[] 存储更紧凑
- 避免混入大量中文、emoji 等 UTF-16 字符,否则 coder 切换为 UTF16,每个字符占 2 字节,抵消部分优化
- 可通过 StringLatin1.isLatin1()(非公开 API)或观察 -XX:+PrintGCDetails 中字符串内存占比,间接验证编码策略生效


















