以无参构造为例
第一步:调用add方法添加元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 添加元素前先调用ensureCapacityInternal方法
elementData[size++] = e;//添加对象时,size+1
return true;
}
第二步:调用ensureCapacityInternal方法,设定好minCapacity的值
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//判断是否为空数组
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
当空数组添加第1个元素时,minCapacity=1,调用max()方法取出DEFAULT_CAPACITY和minCapacity的最大值 ,minCapacity变为DEFAULT_CAPACITY(默认大小10),调用ensureExplicitCapacity方法。
当添加第2个元素时,直接调用ensureExplicitCapacity方法。
第三步:调用ensureExplicitCapacity方法修改修改次数,并判断是否需要扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//修改次数加1
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);//调用扩容方法
}
当添加第1个元素时,此时的elementData.length=1(为空列表),minCapacity=10,所以minCapacity>elementData.length,会进入grow(minCapacity)方法(此时minCapacity=10)。
当添加第2个元素时,此时的minCapacity=2,此时elementData.length(即是容量)在添加第一个元素后扩容成10了,所以minCapacity<elementData.length,不会进入grow(minCapacity)方法,数组容量仍为10不变
所以当添加第3、4···到第10个元素时,依然不会执行grow方法,数组容量都为10。
当添加到第11个元素时,(minCapacity=11)>(elementData.length=10),所以进入grow(minCapacity)方法进行扩容。
第四步:调用grow方法进行扩容
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//通过位运算右移一位,相当于除以2,运算速度快,新容量扩大到原容量的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
//从minCapacity和newCapacity种取出一个较大值作为扩容后新数组的容量
//这个if判断主要是针对添加第一个元素时使用,1.5倍的oldCapacity 还是为0,所以newCapacity为最小容量10
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
//如果新容量大于数组的最大size,进入hugeCapacity方法
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//最后将原来的数组和新的容量大小传入到copyOf方法中复制(先设定一个新容量大小的数组,把原数据放入其中即可)
elementData = Arrays.copyOf(elementData, newCapacity);
}
当add第1个元素时,oldCapacity为0,第一个if成立,newCapacity=minCapacity=10;但是第二个if不成立,则不会进入hugeCapacity方法,数组容量为10,add方法中return true,size增为1。
当add第11个元素进入grow方法时,newCapacity为15,比minCapacity(为11)大,第一个if判断不成立。新容量没有大于数组最大size,不会进入hugeCapacity方法。数组容量扩为15,add方法中return true,size增为11。
第五步:如果新容量大于MAX_ARRAY_SIZE,进入hugeCapacity方法
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
本文详细解析了ArrayList在Java中的工作原理,特别是其扩容机制。从add方法开始,逐步介绍了ensureCapacityInternal、ensureExplicitCapacity和grow等关键方法的作用及流程,并讨论了在不同情况下的扩容策略。
2225

被折叠的 条评论
为什么被折叠?



