算法题必须用StringBuilder:因String不可变,拼接导致O(n²)时间复杂度;StringBuilder通过可变char[]实现O(1)均摊追加,支持append、reverse等高效操作,单线程下性能优于StringBuffer。

在算法题中,字符串拼接、构造、翻转、删减等操作频繁出现。用 String 直接拼接(如 s += "a")会导致时间复杂度退化为 O(n²),尤其在循环中极易超时;而 StringBuilder 通过可变字符数组实现 O(1) 均摊追加,是竞赛和刷题场景下的标准解法。
为什么算法题必须用 StringBuilder?
Java 的 String 是不可变对象:每次 + 或 += 都新建一个字符串对象,复制全部字符。假设循环拼接 n 次、总长为 L,则总复制量约为 1 + 2 + 3 + … + L ≈ O(L²),实际运行可能慢 50–100 倍。
StringBuilder 在内部维护 char[],所有修改(append、insert、delete)均原地操作,扩容也仅在容量不足时发生(新容量 = 旧容量 × 2 + 1),均摊时间复杂度稳定在 O(1)。
- LeetCode 中“反转字符串 II”“Z 字形变换”“外观数列”等题,不用 StringBuilder 很难通过全部测试用例
- 输入规模 ≥ 10⁴ 时,String 拼接几乎必然超时;StringBuilder 通常能控制在毫秒级
高频操作写法与避坑点
算法题中不追求代码美观,但需兼顾效率与正确性:
立即学习“Java免费学习笔记(深入)”;
-
追加优先用
append():支持char、int、boolean、String等,无需手动String.valueOf() - 避免在循环内 new StringBuilder():应提前声明一次,在循环中复用;否则等于白用
-
插入/删除注意索引边界:如
delete(start, end)是左闭右开区间,insert(i, s)表示在索引 i 前插入(i 可等于当前长度) -
反转直接调
reverse():比手写双指针更简洁安全,底层也是 char[] 原地交换
容量预估能进一步提速
默认初始容量为 16,若已知最终字符串长度(例如题目给出最大长度限制或可推导),建议显式指定容量:
-
new StringBuilder(1024)可避免多次扩容复制(扩容需拷贝原数组) - 例如处理 10⁵ 个数字的拼接,每个数字最多 10 位,预留 10⁶ 容量更稳妥
- 不确定时可用
ensureCapacity(min)提前兜底,但不如构造时设好高效
单线程场景下,别用 StringBuffer
算法题均为单线程执行,StringBuffer 所有方法加了 synchronized,带来无谓锁开销,实测比 StringBuilder 慢 10%–20%。
- 除非题目明确要求多线程模拟,否则一律选 StringBuilder
- 二者 API 完全一致,替换成本为零,但性能差异真实存在


















