单线程高频字符串拼接必须用stringbuilder:循环≥5次且每次追加超10字符、拼接逻辑分散、需动态修改或已知最终长度时均应强制替换;初始化须预估容量,避免扩容开销;禁用循环内string+=,优先链式调用,勿用static共享,单线程无需stringbuffer。

单线程高频字符串拼接必须用 StringBuilder,不是“可以选”,而是“应该强制替换”——因为 String 每次拼接都新建对象,10 万次循环可能生成 10 万个临时字符串,触发频繁 GC,而 StringBuilder 复用同一块内存,性能差距常达几十倍。
哪些场景算“高频拼接”
满足以下任一条件,就该立刻换 StringBuilder:
- 循环次数 ≥ 5,且每次追加内容平均超 10 字符(例如拼日志行、生成 HTML 表格、组装 SQL WHERE 条件)
- 拼接逻辑分散在多个方法或回调中(如递归生成 JSON、模板引擎嵌套填充)
- 需动态插入前缀、删末尾逗号、替换某段内容(String 不支持原地修改)
- 已知最终长度范围(比如导出 5000 条记录,每条约 80 字符),可预设容量避免扩容
初始化时一定要预估容量
new StringBuilder() 默认容量只有 16,稍一拼接就扩容;每次扩容都要复制整个数组,公式是 新容量 = 旧容量 × 2 + 2,开销不小。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 能粗算总长就直接指定:比如拼 200 个平均 30 字符的字段 + 199 个逗号 → 200×30+199 ≈ 6199,写
new StringBuilder(6200) - 不确定但数据量大(如万级日志缓冲),宁可略高估(如设 8192),比反复扩容更省
- 若从已有字符串起步,可用
new StringBuilder(str.length() + 预估增量)
写法上要避开常见坑
换了 StringBuilder 不等于自动变快,关键看怎么用:
- 禁用循环内
String +=:它等价于每次 new StringBuilder().append().toString(),白换 - 优先链式调用:
sb.append("a").append("b").append("c"),干净又高效 - 别把 StringBuilder 放进 static 字段供多处共用——单线程也容易错乱,局部变量最安全
- toString() 后如果只取子串,注意别长期持有整个结果,否则可能意外留住大 char[]
不用 StringBuffer,除非真有多线程共享修改
StringBuffer 和 StringBuilder 底层扩容逻辑一样,但 StringBuffer 所有方法都加 synchronized,单线程下纯属多余开销。
- 99% 的业务代码是单线程局部拼接(方法内、日志组装、JSON 构建),直接用 StringBuilder
- 真需要多线程共用时,优先考虑 ThreadLocal
或每次新建,而不是硬上 StringBuffer - 误用 static StringBuffer/StringBuilder 是典型并发 bug 温床,调试困难且性能不升反降
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










