为什么Java中每次手动新建StringBuilder比直接String拼接耗时更短?
性能差异核心原因分析
这个差异本质是javac编译+=字符串拼接时的默认StringBuilder初始化逻辑带来的额外开销,核心有两点:
1. 初始容量分配带来的冗余内存操作
你反编译看到的逻辑相近只是上层流程一致,底层的数组分配逻辑完全不同:
- 直接
String +=的写法会被javac固定编译为:
无参构造的StringBuilder初始容量仅为16,当循环执行几次后result长度超过16,每次循环都需要触发一次扩容逻辑:先计算所需容量,抛弃初始的16长度char数组,重新分配一个足够大的新数组,哪怕扩容时不需要拷贝有效字符(初始count为0),20万次循环累积的小对象分配、扩容计算、GC开销也非常可观。result = new StringBuilder().append(result).append(String.valueOf(i)).toString(); - 手动
new StringBuilder(result)的写法,调用的是带String参数的构造函数,会直接以result.length() + 16为初始容量分配数组,本次要拼接的数字长度最多只有6位,剩余容量完全足够,不需要走任何扩容逻辑,也不会产生多余的废弃小对象。
2. 方法调用的累积开销
+=编译后的逻辑需要调用两次append方法:先append原字符串,再append拼接内容。每次append都要做参数非空校验、长度计算、容量校验等逻辑,20万次循环下两次调用比构造函数内完成原字符串拷贝+单次append的额外开销也会被放大。
最后补充:这两种写法本质都是非常低效的,都属于每次循环都新建StringBuilder并全量拷贝字符串的O(n²)复杂度操作,正确的优化方式是把StringBuilder的初始化提到循环外部,全程复用同一个实例,性能会比这两种写法高几十到上百倍。
内容的提问来源于stack exchange,提问作者cbender
相关产品推荐
相关产品推荐

