Java ArrayList扩容机制
2021/7/17 22:05:50
本文主要是介绍Java ArrayList扩容机制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
java ArrayList扩容机制jdk16
- 1、无参构造
- 2、有参构造
本文基于jdk16,其他版本jdk思想是相同的,只不过调用的方法可能有所不同,本文如果存在问题,请求大佬给予指点。
1、无参构造
ArrayList使用无参构构造,第一次添加将ArrayList中存放数据的elementData容量扩容为10
从上面断点处进入ArrayList的无参构造中
//ArrayList的元素都被存储在elementData中 此处使用transient关键字代表该字段为瞬时态,无法序列化 transient Object[] elementData; //无参构造初始化赋值给elementData的空数组 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //ArrayList的无参构造 public ArrayList() { //将elementData赋值为空数组 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
第一次给arrayList添加元素
从上面断点中进入以下源码
//此处的modCount意义为arrayList被修改的次数 防止多线程操作ArrayList导致出现错误 protected transient int modCount = 0; //此处的size代表的是当前需要赋值的索引值,int类型默认为0 private int size; public boolean add(E e) { //被修改的次数加1 modCount++; //调用add方法 add(e, elementData, size); return true; }
从上面add(e, elementData, size);进入到下面的方法中
private void add(E e, Object[] elementData, int s) { //此处判断当前需要赋值的索引值是否等于elementData的长度 //如果相等的话,说明当前的elementData的容量不足了,需要进行扩容 if (s == elementData.length) //调用grow()函数对elementData进行扩容 elementData = grow(); //将需要添加的元素添加到elementData中 elementData[s] = e; //对size进行加1,为下一添加的元素的索引值 size = s + 1; }
上面代码中调用的grow()函数
private Object[] grow() { //上面代码中调用的grow()函数 return grow(size + 1); }
上面代码中进入的函数,第一次添加元素,走else
private static final int DEFAULT_CAPACITY = 10; //上面代码中进入的函数 //minCapacity此处为1 private Object[] grow(int minCapacity) { //目前的容量即elementData的当前长度 int oldCapacity = elementData.length; //如果当前的elementData不为无参构造所赋值的默认空数组进入if中,否则进入else if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //newCapacity为新的容量 大概意思为在oldCapacity的基础上在加上oldCapacity >> 1的值 //即相当于int newCapacity = oldCapacity + (oldCapacity >> 1) //也相当于int newCapacity = oldCapacity + oldCapacity * 0.5 //newCapacity为oldCapacity乘以1.5 int newCapacity = ArraysSupport.newLength(oldCapacity, minCapacity - oldCapacity, /* minimum growth */ oldCapacity >> 1 /* preferred growth */); return elementData = Arrays.copyOf(elementData, newCapacity); } else { //从DEFAULT_CAPACITY和minCapacity中取出最大数,创建数组 //因为只有elementData为无参构造所赋值的默认空数组才会进入这里 //说明当使用无参构造创建ArrayList时,当第一次添加元素时,会将容量扩容为10 return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)]; } }
从上面代码返回回去,到下面代码中,将元素添加到elementData中
private void add(E e, Object[] elementData, int s) { if (s == elementData.length) elementData = grow(); //将需要添加的元素添加到elementData中 elementData[s] = e; //对size进行加1,为下一添加的元素的索引值 size = s + 1; }
第一次添加元素,调用无参构造,将容量扩容为了10,若之后还需再次扩容,则会将容量扩展为原来的1.5倍
当不需要扩容时,会在下面的语句中直接进行元素的添加,并返回
private void add(E e, Object[] elementData, int s) { //此处判断当前需要赋值的索引值是否等于elementData的长度 //此时if语句不满足,直接进行赋值 if (s == elementData.length) elementData = grow(); //将需要添加的元素添加到elementData中 elementData[s] = e; //对size进行加1,为下一添加的元素的索引值 size = s + 1; }
中间一些步骤与上面相同,不同的只有扩容时不同,此处只展示扩容时,中间步骤跳过
//此时minCapacity为size加1,之前添加了10个元素,所以这里为11 private Object[] grow(int minCapacity) { //oldCapacity为当前elementData的长度即为10 int oldCapacity = elementData.length; //if判断满足,进入if中 if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //newCapacity为新的容量 大概意思为在oldCapacity的基础上在加上oldCapacity >> 1的值 //即相当于int newCapacity = oldCapacity + (oldCapacity >> 1) //也相当于int newCapacity = oldCapacity + oldCapacity * 0.5 //newCapacity为oldCapacity乘以1.5 int newCapacity = ArraysSupport.newLength(oldCapacity, minCapacity - oldCapacity, /* minimum growth */ oldCapacity >> 1 /* preferred growth */); //将得到的新的elementData返回 通过Arrays.copyOf得到的数组会保留之前的数据 return elementData = Arrays.copyOf(elementData, newCapacity); } else { return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)]; } }
2、有参构造
如果使用指定容量的构造器,则初始elementData的容量为指定容量
从当前断点进入到有参构造中
private static final Object[] EMPTY_ELEMENTDATA = {}; //ArrayList有参构造 initialCapacity创建对象时传入的容量大小 public ArrayList(int initialCapacity) { //如果容量大小大于0,则创建指定容量的数组进行返回 if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; //如果容量大小等0,则创建的数组为空数组,与无参构造相同 } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
总结:
1、ArrayList中维护了一个Object类型的数组elementData
transient Object[] elementData;
2、当使用无参构造创建ArrayList对象时,则初始化的elementData容量为0,当添加第一个元素时,会扩容为10,如需再次扩容,则扩容为原来容量的1.5倍(代码中是在原来容量的基础上加上原来容量数右移1位)
3、当使用有参构造创建ArrayList对象时,则初始化的elementData容量为指定容量大小,如果需要再次扩容,则扩容为原来容量的1.5倍(代码中是在原来容量的基础上加上原来容量数右移1位)
这篇关于Java ArrayList扩容机制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南