Java ArrayList扩容机制
- ArrayList中维护了一个Object类型的数据,elementData
-
transient Object[] elementData;
-
//transient表示该对象不会被序列化(序列化——把Java对象转换为字节序列的过程)
-
当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容为10,如果需要再次扩容,则扩容为elementData为1.5倍
-
如果使用的是指定大小的构造器,则初始化elementData容量为指定大小,如果需要扩容,则直接扩容为elementData为1.5倍
通过下列示例来说明该机制
package gather.collection.list;
import java.util.ArrayList;
@SuppressWarnings({"all"})//抑制警告
/**
* @Author Blueshadow
* @Date 2021/7/20 11:00
* @Version 1.0
*/
public class list {
public static void main(String[] args) {
ArrayList list = new ArrayList();//elementData数组初始大小为0
for (int i = 0; i < 10 ; i++) {
list.add(i);
}
list.add(100);
list.add(200);
list.add(null);
for (Object object : list) {
System.out.println(object);
}
}
}
底层源码说明
第一次初始化,创建了一个名为elementData的Object类型的数组,该数组可以存放多种类型的数据,主要是通过包装类来实现。
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
//private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//创建Object类型数组
//创建了一个空数组,并将数组命名为 elemenrData
}
下一步:在执行list.add(1)时,会先进性判断,是否需要扩容,然后再执行赋值操作。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 判断Increments modCount!!
elementData[size++] = e;//赋值操作
return true;
}
下一步:判断是空,则给数组赋予一个最小容量,第一次add,最小容量为minCapacity。
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//先确定elementData是否是一个空数组:
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//先确定最小容量minCapacity(第一次扩容为10)
}
ensureExplicitCapacity(minCapacity);//真正确定是否扩容
}
下一步:进行底层的扩容。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//记录当前集合被修改的次数
// overflow-conscious code
if (minCapacity - elementData.length > 0)//如果elementDara容量不够,就调用grow方法进行扩容
grow(minCapacity);//进行底层的扩容
}
第一次扩容最后一步:底层按照1.5倍进行扩容
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;//第一次oldCapacity=0
int newCapacity = oldCapacity + (oldCapacity >> 1);//原先数组大小+原先数组大小/2
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);//elementData={},使用该方法将newCapacity赋值给elementData
}