arraylist扩容为1.5倍通过位运算int newcapacity = oldcapacity + (oldcapacity >> 1)实现,非浮点乘法;首次扩容默认为10,后续按该公式增长;真正开销在system.arraycopy复制数据的o(n)操作。

ArrayList底层数组扩容为1.5倍,不是靠浮点乘法,而是用位运算高效实现的;核心收益在于平衡内存占用和复制频次,避免频繁扩容带来的性能抖动。
扩容触发的实际检查逻辑
每次调用 add() 之前,都会执行容量校验:
size + 1 > elementData.length
只要待插入后元素总数超过当前数组长度,就立刻扩容——不是等“填满”才扩,而是提前防御。
- 例如:容量为10、已存10个元素,第11次add()调用前就触发扩容(此时 size 还是10,但 10+1 > 10 成立)
- addAll() 同理,会检查 size + 集合大小 > 当前长度,满足即扩
1.5倍是怎么算出来的
关键代码在 grow(int minCapacity) 方法中:
int newCapacity = oldCapacity + (oldCapacity >> 1);
这等价于 oldCapacity × 1.5,但全程使用整数位运算,无浮点开销、无舍入误差。
- 10 → 10 + (10 >> 1) = 10 + 5 = 15
- 15 → 15 + (15 >> 1) = 15 + 7 = 22
- 22 → 22 + (22 >> 1) = 22 + 11 = 33
首次添加时若用无参构造,oldCapacity 为0,直接跳过该公式,取默认值10。
扩容真正耗时在哪
计算新容量只是毫秒级操作;真正开销来自数据迁移:
- 调用 Arrays.copyOf(elementData, newCapacity)
- 底层依赖 System.arraycopy,逐字节复制原数组全部有效元素
- 时间复杂度为 O(n),n 是当前 size
- 同时引发临时对象堆压力,可能触发 Minor GC
为什么选1.5而不是其他倍数
这是空间与时间权衡的结果:
- 比2倍更省内存:避免过度预留(如从10→20,多占10个空位)
- 比1.2倍更少复制:减少扩容总次数(10→12→14→16…需更多轮)
- 位运算天然适配:右移1位 ≈ 除以2,整数运算快且确定性强
- 实测表明:1.5倍在常见业务写入模式下综合性能最优











