arraylist扩容核心路径是add→grow,三步:检测容量、计算新容量(old*1.5)、复制数组;默认构造首次add扩容至10,new arraylist(0)则从1开始低效扩容。

直接看 add 方法入口,再顺藤摸到 grow(),这是理解 ArrayList 动态扩容最短也最准的路径。
核心逻辑就三步:检测容量 → 计算新容量 → 复制数组
ArrayList 扩容的关键源码位置(JDK 8+)
add(E e) 是触发扩容的起点:
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length) // 关键判断:size 已等于数组长度
elementData = grow(); // 容量不足,进扩容
elementData[s] = e;
size = s + 1;
}
真正干活的是 grow() 方法:
private Object[] grow() {
return grow(size + 1); // 至少需要容纳 size+1 个元素
}
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 等价于 old * 1.5
if (newCapacity - minCapacity <p>注意两个细节:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2870" title="Gradle 9.8.0"><img
src="https://img.php.cn/upload/manual/001/431/639/6ad9ce71d8cb6379.png" alt="Gradle 9.8.0" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2870" title="Gradle 9.8.0" class="overflowclass">Gradle 9.8.0</a>
<p class="overflowclass"></p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2870" title="Gradle 9.8.0" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
-
oldCapacity >> 1是位运算,比oldCapacity / 2更快; -
Arrays.copyOf内部调用System.arraycopy,是 native 方法,高效但有开销。
不同构造方式对首次扩容的影响
构造方式决定了 elementData 初始指向哪个空数组,进而影响第一次 add 的行为:
new ArrayList()
→elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA
→ 第一次add时,grow(1)会被修正为grow(10),直接分配长度为 10 的数组。new ArrayList(0)
→elementData = EMPTY_ELEMENTDATA
→ 第一次add按常规逻辑走,oldCapacity=0,newCapacity=0,最终设为minCapacity=1,后续扩容节奏变成 1→2→3→4→6→9→13… 频繁复制。new ArrayList(n)(n > 0)
→ 直接创建长度为 n 的数组,跳过首次扩容,适合预估数据量的场景。
如何验证扩容行为?
可以用反射读取 elementData.length,或借助 ArrayList.size() 和 ArrayList 实际内存占用对比观察。简单验证示例:
ArrayList<string> list = new ArrayList();
System.out.println("初始容量: " + getCapacity(list)); // 0(因懒加载)
list.add("a");
System.out.println("add 1 次后: " + getCapacity(list)); // 10
list.add("b");
System.out.println("add 2 次后: " + getCapacity(list)); // 还是 10(没触发扩容)
// …直到第 11 次 add,才会 grow 到 15</string>
(getCapacity 可通过反射获取 elementData.length,仅用于调试)
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










