ArrayList 原理
成员变量和构造方法

private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
- 定义了两个空数组成员变量,这两个成员变量除了名字不一样,别的都是一样的
- 虽然能根据源码看出使用不同的构造方法创建 ArrayList 时,会使用不同的变量,但是为什么不定义一个,两个构造方法都是用这个变量呢?原因是少扩容
- DEFAULTCAPACITY_EMPTY_ELEMENTDATA 在第一次 add 的时候会创建一个长度是 10 的数组,当元素数量 <= 10 时不会触发扩容
- EMPTY_ELEMENTDATA 不会创建 10 个长度的数组,就是空数组,所以相比于 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 扩容次数更多
- 每次扩容是 1.5 倍,并且还是 static 修饰的(共享变量),长度也只是 10,这么一点点内存都要省下来,简直煞费苦心用心良苦!!!
添加元素和扩容
public boolean add(E e) {
modCount++; // 修改次数+1
// 再调用本来的 add 完成元素的添加
add(e, elementData, size);
return true;
}
// 三个参数分别是:添加的元素、list的数组、list的元素个数
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length) // 如果 list.size 等于数组长度,就扩容(size 是元素个数,size 一定 <= 数组长度)
elementData = grow(); // 扩容方法,返回扩容后的数组,内部也把原来数组的数据拷贝到这个新数组了
elementData[s] = e; // 元素放入数组
size = s + 1; // list 容量+1
}
// grow 方法再调用另一个 grow 方法
private Object[] grow() {
return grow(size + 1); // size => list 元素个数(为什么要加1,添加了一个元素后 size 就要增加 1)
}
// minCapacity 是新 size
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length; // 数组长度
// 如果数组元素不为 0 也就是目前已经保存的有元素了,或者 elementData 不为 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 就走这里
// 两种情况:1,有参构造(参数是0)创建的 ArrayList 初次添加元素;2:数组已经有元素了
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 扩容,得到一个新的数组长度(前面 add 方法有条件别忘了,就是数组长度和list.size相同)
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
// 拷贝原来的元素到新的数组中
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
// 只有一种情况会走这里,使用无参构造创建的 ArrayList 初次添加元素,DEFAULT_CAPACITY 是 10,所以这里会创建要给长度是 10 的数组
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
具体怎么得到新的长度的,新的长度是多少?关键是这行代码
// oldCapacity:list 原 size(传来的是原数组长度,也就是原 size,因为前提条件是数组长度 == size)
// minCapacity:list 新 size(新 size 比原 size 大 1,因为增加的是一个元素)
// oldCapacity >> 1:右运算,减少一半(list 原 size 的一半)
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
ArraysSupport.newLength 具体做了什么
// 三个参数分别是:list 原 size、1、list 原 size 的一半
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// Math.max(minGrowth, prefGrowth) 取大的是 prefGrowth(也就是原 size 的一半)
// 所以 prefLength = 原 size + 0.5 * 原 size,也就是原 size 的 1.5 倍,这就是新的数组长度
int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflow
// SOFT_MAX_ARRAY_LENGTH 是个静态常量 Integer.MAX_VALUE - 8,在 Integer.MAX_VALUE 附近不同的 vm 规范不一致,为了保险起见设置一个软最大长度
if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
// 返回原 size 的 1.5 倍
return prefLength;
} else {
// 新数组长度如果大于 Integer.MAX_VALUE - 8
return hugeLength(oldLength, minGrowth);
}
}
private static int hugeLength(int oldLength, int minGrowth) {
// 就不扩容了,因为已经达到 Integer.MAX_VALUE - 8,再来个 1.5 倍肯定超过 Integer.MAX_VALUE,直接原 size + 新元素个数
int minLength = oldLength + minGrowth;
// 如果大于 Integer.MAX_VALUE 抛出 OOM(Integer.MAX_VALUE + 1 就是一个负数了)
if (minLength < 0) { // overflow
throw new OutOfMemoryError(
"Required array length " + oldLength + " + " + minGrowth + " is too large");
} else if (minLength <= SOFT_MAX_ARRAY_LENGTH) {
return SOFT_MAX_ARRAY_LENGTH;
} else {
return minLength;
}
}
批量添加元素
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray(); // 新元素转数组
modCount++; // 修改次数+1
int numNew = a.length; // 新元素个数
if (numNew == 0) // 扯犊子
return false;
Object[] elementData;
final int s;
// list 里的原数组是否能容纳下 numNew,如果装不下就扩容,如果装的下直接放(数组长度 >= list.size)
if (numNew > (elementData = this.elementData).length - (s = size))
elementData = grow(s + numNew); // 扩容方法
System.arraycopy(a, 0, elementData, s, numNew); // 拷贝
size = s + numNew; // 维护 size
return true;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具