20220930-ArrayList扩容机制源码分析②

本部分对于使用设置初始容量的方法创建ArrayList集合的方式进行源码分析。

代码

public class ArrayListSource {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList(5); //跳转至第一步
for (int i = 0; i < 50; i++) {
arrayList.add(i);
}
}
}

底层代码

第一步:

public ArrayList(int initialCapacity) { //initialCapacity = 5
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity]; //elementData = {null, null,null,null,null}
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}

由上ArrayList带参构造器内容可知:

  1. 当初始容量显示的设置为0时,与默认无参构造器执行方式相同,都是将elementData设置为空数组。
  2. 当初始容量大于0时,将创建一个Object类型数组,数组大小等于初始容量。
  3. 当初始容量小于0时,将抛出异常对象IllegalArgumentException

第二步:
创建完成arrayList集合之后,进入for循环,从i=0开始,执行arrayList.add(i)方法,底层代码如下:

public boolean add(E e) { //e = 0
modCount++; //modCount=0,执行之后自加1
add(e, elementData, size); //跳转至第三步
return true;
}

第三步:

//e = 0
//elementData = {null, null,null,null,null}
//elementData.length = 5
//s = 0
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length) //此时if语句不成立
elementData = grow();
elementData[s] = e; //elementData = {{0, null,null,null,null}
size = s + 1; //size = 1
}

第四步:
程序继续执行for循环,直到size=5时,表示集合中元素已经达到容量上限,程序执行第三步中的if语句,对集合进行扩容

private Object[] grow() {
return grow(size + 1); //size = 6,跳转至第五步
}

第五步:

//elementData.length = 5
//minCapacity = 6
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length; //oldCapacity = 5
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //if语句条件成立
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */); //跳转至第六步
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}

第六步:

//oldLength = 5
//minGrowth = 1
//prefGrowth = 2
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// assert oldLength >= 0
// assert minGrowth > 0
int newLength = Math.max(minGrowth, prefGrowth) + oldLength; //newLength = 7
if (newLength - MAX_ARRAY_LENGTH <= 0) { //if条件成立
return newLength; //返回第5步
}
return hugeLength(oldLength, minGrowth);
}

第七步:
程序执行elementData = Arrays.copyOf(elementData, newCapacity);
elementData = {0 , 1 , 2 , 3 , 4 , null , null , null}
程序继续执行for循环,当达到集合的容量上限值,继续进行扩容,扩容后的容量=原容量*1.5

posted @   淡忘的江南  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示