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带参构造器内容可知:
- 当初始容量显示的设置为0时,与默认无参构造器执行方式相同,都是将elementData设置为空数组。
- 当初始容量大于0时,将创建一个Object类型数组,数组大小等于初始容量。
- 当初始容量小于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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)