ArrayList扩容触发条件是add时size等于capacity;底层用Object[]存储,初始容量10;扩容按1.5倍增长,公式为newCapacity = oldCapacity + (oldCapacity >> 1);通过Arrays.copyOf实现新数组创建与数据复制;空参构造采用懒初始化,首次add才分配数组;并发add可能导致数据丢失或异常,因其线程不安全。

扩容触发条件:add 时 size == capacity
ArrayList 底层用 Object[] elementData 存储元素,初始容量默认为 10(JDK 8+)。每次调用 add(E e) 添加元素前,会检查当前元素个数 size 是否已等于数组长度 capacity。相等即触发扩容,否则直接赋值。
扩容计算公式:newCapacity = oldCapacity + (oldCapacity >> 1)
扩容不是翻倍,而是按 **1.5 倍**增长:
- oldCapacity 为 10 → newCapacity = 10 + (10 >> 1) = 10 + 5 = 15
- oldCapacity 为 15 → newCapacity = 15 + 7 = 22(右移取整,15>>1=7)
- 后续依次为 33、49、73……增长幅度递减,但始终 >1.5×(因整数截断)
扩容底层操作:Arrays.copyOf 创建新数组 + System.arraycopy 复制
扩容本质是「新建更大数组 + 拷贝原数据」:
- 调用 Arrays.copyOf(elementData, newCapacity),内部用 System.arraycopy 实现高效复制
- 旧数组失去引用,等待 GC;新数组成为 elementData
- 注意:ensureCapacity() 可主动预扩容,避免频繁 resize 影响性能
特殊场景补充:空参构造 + 首次 add 的“懒初始化”
使用 new ArrayList() 时,elementData 并非 new Object[10],而是指向共享的 EMPTY_ELEMENTDATA。直到第一次 add 才真正分配 10 长度数组——这是 JDK 8 引入的优化,节省无添加场景的内存开销。
立即学习“Java免费学习笔记(深入)”;
高频陷阱提醒:并发扩容导致数据丢失或异常
ArrayList 本身线程不安全。多线程同时 add 可能出现:
- 两个线程都判断需扩容 → 都创建新数组 → 后续复制覆盖,部分元素丢失
- 一个线程刚完成扩容赋值,另一个线程仍操作旧数组 → 报 ArrayIndexOutOfBoundsException 或数据错乱
- 解决方式:用 CopyOnWriteArrayList(读多写少)、Vector(同步方法,性能低)、或外层加锁


















