ArrayList的扩容
ArrayList的介绍
- ArrayList是List接口下的一个实现类,它可以动态的修改数组。
- 可以加入null,并且可以加入多个。
- 是由数组来实现存储数据的。
- ArrayList基本等同于Vector,但是ArrayList是线程不安全的。
- ArrayList中维护了一个Object类型的数组elementData。
使用无参构造器创建ArrayList数组时的扩容(一)
public class ArrayListSource {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
for (int i = 1; i < 11; i++) {
arrayList.add(i);
}
arrayList.add(100);
arrayList.add(200);
arrayList.add(300);
arrayList.add(400);
}
}
ArrayList arrayList = new ArrayList();
使用无参构造函数创建对象,先会创建一个空的elementData数组
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
(第一次进入add添加数字)for循环添加数字的时候,会首先进行一个装箱操作。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
然后进入ArrayList类的add方法。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
add方法中首先判断是否需要扩容,进入ensureCapacityInternal方法。
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//第一次进入该方法时,两个数组相同,if判断为true
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
//private static final int DEFAULT_CAPACITY = 10;
//将两者中的大的那个赋给minCapacity,传入的minCapacity为1,经过赋值操作后,变为了10
}
ensureExplicitCapacity(minCapacity);
}
进入ensureExplicitCapacity方法确认是否需要扩容。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//此时minCapacity大小为10,数组长度为0,所以if判断为true,进入grow真正的扩容方法
grow(minCapacity);
}
进入grow扩容。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
//>>右移运算相当于除以2
//oldCapacity=newCapacity=0
if (newCapacity - minCapacity < 0)
//if判断为true,newCapacity的值变为10
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
//判断数组容量是否大于最大值
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
//进行数组的拷贝
}
依次返回后,将数据存入数组下标为0的地方。然后执行size++。
执行完上述操作后,集合的大小就变为了10,并且可以看到在0的位置存入了数据。
实际上第一次没有真正用到1.5倍的扩容。
使用无参构造器创建ArrayList数组时的扩容(二)
第二次进入for循环的add方法时,在ensureCapacityInternal方法中,if判断为false,直接进入ensureExplicitCapacity方法。
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
//此时传入的参数为数组中数据个数多少再加1,minCapacity=2
}
ensureExplicitCapacity方法中,不进入grow。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//minCapacity为2,elementData.length为10,不进入grow方法
grow(minCapacity);
}
返回后,将数据存入下标为1的地方。执行size++。
重复上述操作,直到for循环结束,存入十个数据。
使用无参构造器创建ArrayList数组时的扩容(三)
执行arrayList.add(100);也先进行装箱操作。
再进入add,直到进入方法ensureExplicitCapacity.
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//此时数组元素已满,minCapacity的值为11,大于数组的长度,所以要进入grow方法,进行扩容
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
在grow方法中,将数组长度10赋值给oldCapacity。
新的数组容量newCapacity为原来数组容量的长度10加上,原数组长度除以2的值5,所以最后newCapacity的大小为15。
两个if判断都为false,最后执行Arrays.copyOf。
扩容后的数组大小为15。
使用有参构造器创建ArrayList数组时的扩容(一)
public class ArrayListSource {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList(8);
for (int i = 1; i < 9; i++) {
arrayList.add(i);
}
arrayList.add(100);
arrayList.add(200);
arrayList.add(300);
arrayList.add(400);
}
}
创建对象时,直接创建一个指定大小的数组。
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
然后进入for循环,先装箱,再进入add方法——ensureCapacityInternal方法。
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
if判断为false,直接进入ensureExplicitCapacity。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
minCapacity的值为1,数组长度为8。if判断为false,返回,加入数据,size++。
使用有参构造器创建ArrayList数组时的扩容(二)
执行arrayList.add(100);
经过add——ensureCapacityInternal,直接进入ensureExplicitCapacity。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
minCapacity的值为9,elementData.length的值为8,进入grow方法扩容。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
oldCapacity=8
newCapacity=8+4=12
不进入if,执行拷贝,扩容成功。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)