为什么 StringBuilder 这么快?带你看懂底层实现

原文来自于:zha-ge.cn/java/30

为什么 StringBuilder 这么快?带你看懂底层实现

一个普通工作日的"性能危机"

那天下午,我正在优化一个数据处理模块。代码跑得慢得要命,CPU 使用率飙到 90%,领导催得紧。打开性能分析工具一看,竟然发现罪魁祸首是一个看似无害的字符串拼接循环:

java 复制代码
String result = "";
for (int i = 0; i < 10000; i++) {
    result += "item_" + i + ",";
}

这段代码要处理一万条数据,结果跑了将近 30 秒!我当时就懵了,不就是个字符串拼接吗,怎么会这么慢?

探索:String 的"黑暗秘密"

好奇心驱使我深入挖掘。原来,Java 中的 String 是不可变对象 ,每次 += 操作实际上都会:

  1. 创建一个新的 String 对象
  2. 把原字符串内容复制过去
  3. 把新内容追加上
  4. 丢弃旧对象

想象一下,一万次循环就是一万次"搬家"!每次都要把所有家当重新打包,能不累死吗?

转折:StringBuilder 的"魔法"登场

同事提醒我试试 StringBuilder。我半信半疑地改了代码:

java 复制代码
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.append("item_").append(i).append(",");
}
String result = sb.toString();

结果让我大跌眼镜------从 30 秒变成了 0.05 秒!简直像是给程序装了火箭发动机。

解密:StringBuilder 的底层"黑科技"

我迫不及待地翻看了 StringBuilder 的源码,发现了它的秘密武器:

java 复制代码
public StringBuilder append(String str) {
    super.append(str);
    return this;
}

// AbstractStringBuilder 中的核心逻辑
void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    if (newCapacity < minimumCapacity)
        newCapacity = minimumCapacity;
    value = Arrays.copyOf(value, newCapacity);
}

原来 StringBuilder 内部维护了一个可变的字符数组!它的聪明之处在于:

特性 StringBuilder String
存储方式 可变字符数组 不可变对象
容量策略 动态扩容(2倍+2) 每次新建
内存复制 仅扩容时 每次操作

踩坑瞬间

不过,我也遇到了一些意想不到的坑:

坑1:忘记设置初始容量 默认容量只有 16,频繁扩容还是会影响性能。对于大量数据,最好预估容量:

java 复制代码
StringBuilder sb = new StringBuilder(10000); // 预分配足够空间

坑2:多线程使用 StringBuilder 不是线程安全的!多线程环境下要用 StringBuffer,或者各线程独立使用。

坑3:过度优化 少量字符串拼接(比如 2-3 个),直接用 + 反而更简洁。编译器会自动优化成 StringBuilder。

经验启示

这次"性能危机"让我明白了几个道理:

  • 不要小看基础 API:String 和 StringBuilder 看似简单,底层机制却大有玄机
  • 性能问题要从根源找:不是代码写得不够复杂,而是用错了工具
  • 合适的数据结构是王道:可变 vs 不可变,一字之差,性能天壤之别

现在每当看到循环中的字符串拼接,我都会条件反射般想起那个惊心动魄的下午。StringBuilder 不只是一个工具类,更像是 Java 工程师的"性能救星"------它用一个简单的可变数组,解决了字符串操作的性能瓶颈。

记住这个故事,下次遇到类似场景,你就知道该选谁了!

相关推荐
spencer_tseng19 分钟前
Redis + Nacos.bat
java·windows·dos
troyzhxu1 小时前
列表查询的 GraphQL —— 一行代码终结你的 if-else 地狱!
java·springboot·graphql
孫治AllenSun2 小时前
【DataX】生产环境搭建DataX集群案例
java·开发语言·jvm
好好沉淀3 小时前
@NotBlank(message = “{xxx}“) 注解中花括号的含义
java
fīɡЙtīиɡ ℡3 小时前
内存泄漏产生的原因
java·spring·servlet
码智社4 小时前
Java实现RSA密钥生成、加密解密、加签验签
java
wear工程师4 小时前
ThreadLocal 在线程池里为什么会串数据:别只会答内存泄漏
java·后端
Iruoyaoxh4 小时前
栈和队列~
java·开发语言
审小匠OpenCPAi4 小时前
银行流水核查怎么自动化?单边匹配、双向勾稽与图聚类异常检测的工程对比
java·前端·人工智能·python·审计
码上上班4 小时前
docker课程
java·docker·容器