ArrayList扩容触发时机是add时size等于elementData.length,新容量为原容量1.5倍(oldCapacity + oldCapacity >> 1),不足则取minCapacity,溢出时调用hugeCapacity;初始化默认容量10,可预估容量或ensureCapacity优化,扩容为O(n)复制操作。

ArrayList 在容量不足时会自动扩容,核心逻辑是创建一个更大的新数组,并把原数组元素复制过去。默认扩容为原容量的 1.5 倍(即 oldCapacity + oldCapacity >> 1),且保证最小增长量至少为 1。
扩容触发时机
当执行 add(E e) 方法且当前元素个数(size)等于底层数组长度(elementData.length)时,就会触发扩容。注意:不是“写入第 capacity+1 个元素时”才扩容,而是“添加导致 size 超出当前数组长度时”立即扩容。
- 构造时未指定初始容量,默认容量为 10
- 即使调用 ensureCapacity(int minCapacity) 预留空间,也不会主动缩小或提前扩容,只在真正需要时生效
- addAll() 批量添加也会触发扩容,计算依据是当前 size 加上待添加集合的大小
扩容的具体计算方式
扩容后的新容量由 grow(int minCapacity) 方法决定:
- 先尝试:newCapacity = oldCapacity + (oldCapacity >> 1),即增加 50%
- 如果该值仍小于所需最小容量(比如因初始容量为 0 或极小值),则直接设为 minCapacity
- 若 newCapacity 溢出(超过 Integer.MAX_VALUE),会调用 hugeCapacity(minCapacity),按需设为 Integer.MAX_VALUE 或 MAX_ARRAY_SIZE(即 Integer.MAX_VALUE - 8)
手动控制扩容行为
可以通过以下方式减少不必要的扩容开销:
立即学习“Java免费学习笔记(深入)”;
- 初始化时预估大小,使用 new ArrayList(initialCapacity)
- 已知要添加大量元素前,调用 ensureCapacity(minCapacity) 主动预留空间
- 避免频繁 add 后又 clear,因为底层数组不会自动缩容;如需释放内存,可手动赋值为 new ArrayList<>() 或调用 trimToSize()(将容量收缩到当前 size)
扩容带来的性能影响
扩容本质是一次数组复制(Arrays.copyOf()),时间复杂度 O(n)。虽然平均摊还成本是 O(1),但单次扩容可能引发明显延迟,尤其在大集合场景下:
- 从 10 → 15 → 22 → 33 → 49 …… 每次增长逐步变大,减少了扩容频次
- 若反复增删、size 波动大,建议结合业务节奏批量操作,或改用 LinkedList(但注意随机访问代价高)
- 高并发场景下,ArrayList 本身不安全,扩容更不能并发进行,应选用 CopyOnWriteArrayList 或外加同步控制


















