arraylist扩容本质是“添加前预检+数组拷贝”,核心链路为add→ensurecapacityinternal→grow;首次扩容至10,后续按1.5倍(oldcapacity + oldcapacity>>1)增长,不足则兜底取mincapacity,超integer.max_value-8时进hugecapacity处理。

ArrayList 的扩容不是“自动变大”,而是每次添加元素前先检查空间是否够用,不够就新建数组、复制数据、替换引用。核心逻辑在 add() → ensureCapacityInternal() → grow() 这条链路上,关键在于容量计算、边界处理和内存操作。
扩容触发时机:不是“满了才扩”,而是“要放不下时就扩”
调用 add(E e) 时,第一件事是执行 ensureCapacityInternal(size + 1),即“确保能装下当前 size 加 1 个元素”。只要 size + 1 > elementData.length,就判定需要扩容。
- 无参构造的 ArrayList,首次
add时elementData是空数组(DEFAULTCAPACITY_EMPTY_ELEMENTDATA),此时直接将最小容量设为DEFAULT_CAPACITY(10) - 已指定初始容量(如
new ArrayList(5)),则按实际数组长度判断,满 5 就扩第 6 个 - 使用
ensureCapacity(int minCapacity)可主动触发扩容,常用于预估数据量场景
新容量怎么算:1.5 倍是位运算,但会兜底修正
真正扩容逻辑在 grow(int minCapacity) 方法中:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 旧容量为
oldCapacity = elementData.length - 新容量初值为
oldCapacity + (oldCapacity >> 1),等价于oldCapacity * 1.5,用位运算提升效率 - 若该值仍小于所需最小容量(比如首次扩容时 oldCapacity 为 0,算出来还是 0),则直接取
minCapacity - 若新容量超过
MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8),则进入hugeCapacity()处理,防止数组对象头信息溢出
扩容具体做了什么:本质是一次数组拷贝
确定好新容量后,执行 elementData = Arrays.copyOf(elementData, newCapacity):
-
Arrays.copyOf()底层调用System.arraycopy(),是 JVM 优化过的高效内存复制 - 原数组对象不再被引用,等待 GC;新数组成为
elementData的新引用 - 这个过程时间复杂度是 O(n),所以频繁扩容会影响性能,尤其在大数据量场景
为什么是 1.5 倍?不是 2 倍也不是 1.2 倍
这是空间与时间的平衡选择:
- 2 倍太激进:容易造成大量内存浪费,尤其在多次扩容后,空闲空间占比高
- 1.2 倍太保守:扩容太频繁,O(n) 拷贝次数增多,整体开销反而上升
- 1.5 倍在实践中兼顾了内存利用率和扩容频次,且
oldCapacity >> 1计算快、无浮点误差
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










