arraylist扩容1.5倍源于位运算oldcapacity + (oldcapacity >> 1),首次扩容为0→10,后续按该公式增长;扩容在add/addall前触发,真正耗时的是arrays.copyof导致的o(n)数组拷贝。

ArrayList 扩容 1.5 倍不是 magic number,而是源码中一条位运算语句的自然结果:每次扩容计算新容量时,执行 int newCapacity = oldCapacity + (oldCapacity >> 1)。它不依赖浮点乘法,全程整数运算,高效且无舍入误差。
扩容触发时机:在“放不下之前”就判断
扩容发生在 add() 或 addAll() 调用的最开始,而非数组填满后:
- 调用
add(e)时,先检查size + 1 > elementData.length - 调用
addAll(c)时,检查size + c.size() > elementData.length - 只要待插入后总元素数超过当前数组长度,立刻触发扩容
首次扩容是特例:0 → 10,不走 1.5 倍公式
无参构造 new ArrayList() 使用的是空数组 DEFAULTCAPACITY_EMPTY_ELEMENTDATA(长度为 0):
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 第一次
add()进入calculateCapacity()方法,直接返回Math.max(10, size+1)→ 10 - 后续扩容才进入
grow(),启用oldCapacity + (oldCapacity >> 1)公式 -
new ArrayList(0)行为同无参构造;new ArrayList(1)则直接分配长度为 1 的数组
1.5 倍怎么算:右移一位 ≈ 除以 2
核心代码位于 grow(int minCapacity) 中:
-
oldCapacity >> 1是无符号右移 1 位,等价于整数除以 2(向下取整) - 所以
10 → 10 + 5 = 15,15 → 15 + 7 = 22,22 → 22 + 11 = 33 - 若计算出的
newCapacity仍小于所需最小容量(如addAll(100)时当前容量仅 50),则直接设为minCapacity
真正耗时操作:数组拷贝,不是算容量
确定新容量只是毫秒级计算;实际性能开销来自数据迁移:
- 调用
Arrays.copyOf(elementData, newCapacity) - 底层依赖
System.arraycopy,时间复杂度 O(n),n 是当前size - 复制过程产生临时对象,可能引发 Minor GC,尤其当元素本身含大字段(如 byte[])时更明显
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










