java中stringbuilder扩容公式“旧容量×2+2”源自abstractstringbuilder的expandcapacity()方法,旨在平衡性能与内存预留,每次append或insert时检查容量并触发扩容。

Java 中 StringBuilder 的扩容公式 “旧容量 × 2 + 2” 并非凭空设计,而是源自其父类 AbstractStringBuilder 中的 expandCapacity() 或 ensureCapacityInternal() 方法。这个逻辑在 JDK 源码中清晰可见,核心目的是兼顾性能与内存预留。
扩容触发时机
每次调用 append()、insert() 等修改内容的方法时,都会先检查:
- 当前已使用长度
count加上待追加内容长度是否超过内部数组value.length - 若超出,就进入扩容流程:
ensureCapacityInternal(minimumCapacity)
关键源码逻辑(JDK 8/11 典型实现)
在 AbstractStringBuilder 类中,扩容核心方法类似如下:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length <p>其中:</p>
-
value.length是当前内部数组长度(即当前容量) -
minimumCapacity是本次操作所需的最小总容量(count + len) - 先按
×2 + 2计算新容量,再和minimumCapacity比较,取较大者
为什么是 “×2 + 2” 而不是单纯 ×2?
这个 “+2” 是一个精巧的工程优化,主要考虑两类常见场景:
- 追加完一段字符串后,紧接着要加一个分隔符(如逗号
','或换行符'\n'),而char占 2 字节,+2 可大概率避免下一次单字符 append 触发二次扩容 - 在 Java 9+ 引入 Compact Strings(
byte[] + coder)后,虽然底层可能用byte[],但扩容逻辑仍沿用相同数值策略,保持行为一致
初始容量与实际扩容示例
以无参构造为例:
-
new StringBuilder()→ 初始value.length = 16,count = 0 - 追加 16 个字符后,
count = 16,刚好满;再 append 1 个字符 → 需要容量 ≥17 - 触发扩容:
newCapacity = 16 × 2 + 2 = 34,大于 17,于是分配长度为 34 的新数组 - 若此时需容量为 50(比如一次性 append 很长字符串),则直接取
minimumCapacity = 50,跳过 ×2+2
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










