Java ArrayList扩容
上次我们说到ArrayList扩容机制较复杂,可以单独拿出来讲,这就补上。不附目录,因为适合一步一步理解(>_<)
一、add(E e):
我们先来看add(E e)方法
public boolean add(E e) {
//重点在这里,我们来看ensureCapacityInternal()
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;// 末尾添加元素
return true;
}
二、ensureCapacityInternal()方法:
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
再分别来看calculateCapacity()和ensureExplicitCapacity()方法:
三、calculateCapacity():
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
这里有DEFAULTCAPACITY_EMPTY_ELEMENTDATA,我们再来看这是什么:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};// 空数组
还有DEFAULT_CAPACITY:
private static final int DEFAULT_CAPACITY = 10;// 默认为10
现在我们就可以看懂calculateCapacity()了:
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//判断是否为空
return Math.max(DEFAULT_CAPACITY, minCapacity);// 如果为空,则默认返回10,对应我们初始化容量时的ArrayList
}
return minCapacity;//不为空,则返回传入的值minCapacity
}
所以在扩容时,如果我们是无参初始化的ArrayList,即容量为0,会先将容量赋为10
四、ensureExplicitCapacity()方法:
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)// 判断是否超出界限
grow(minCapacity); // 若超出,则调用grow()方法扩容
}
可知grow()方法是整个扩容机制最重要的一步!
五、grow()方法扩容:
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;// 旧容量
int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量是旧容量的1.5倍
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); //旧容量中存放的内容拷贝给新容量数组
}
我们拿出最关键的两行代码:
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
新的容量是旧容量的(oldCapacity + (oldCapacity >> 1))倍,这也就是我们常说的ArrayList扩容1.5倍。
六、hugeCapacity()分支:
那么还有一条分支:
if (newCapacity - MAX_ARRAY_SIZE > 0)// 新的容量大于数组大小最大值
newCapacity = hugeCapacity(minCapacity);
MAX_ARRAY_SIZE:
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
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;
}
所以不一定是原数组的1.5倍长度,也可能越界抛出异常,也可能返回长度Integer.MAX_VALUE或Integer.MAX_VALUE-8