ArrayList
使用默认构造方法会生成一个长度为0的list
,在调用add()
方法的时候会进行扩容,细说一下扩容机制。
首先,先来看ArrayList中的一些参数:
//默认初始容量大小
private static final int DEFAULT_CAPACITY = 10;
//空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//用于默认大小空实例的共享空数组实例。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//保存的数据
transient Object[] elementData;
private int size;
接着来看构造函数:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
可以发现,使用无参构造的时候构造的是一个空的数组实例,长度为0,当对数组元素进行添加的操作的时候,会扩容容量到10;接下来看看add()
的过程
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
调用add()
方法的时候会调用一个ensureCapacityInternal(size + 1)
方法:
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
进入ensureCapacityInternal(size + 1)
方法后,会调用一个ensureExplicitCapacity
方法,传递的参数为默认容量(10)和传入参数的最大值,第一次add传入的参数为1;
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
在第一次添加元素执行到这个方法的时候,传入的minCapacity
为10,符合判断条件,进入grow
方法:
//要分配的最大数组大小
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
// overflow-conscious code
//old为旧容量,new为新的容量
int oldCapacity = elementData.length;
//可以看出,扩容是使用的位运算,相当于/2,但是效率要高;
//扩容为本来容量的1.5倍左右
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果扩容后的容量还是不够,那么就把最小的需要容量置为扩容后的容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果扩容后的容量大于最大的数组容量,进入hugeCapacity方法
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);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//如果所需的最小容量大于最大数组大小,那么扩容后的容量为Integer的最大值,
//否则为最大的数组大小,
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
到此,扩容结束;再次add元素的时候,minCapacity - elementData.length > 0
不成立,直接在数组后面添加元素并让size++,直到添加第11个元素