您的位置:首页 > 职场人生

ArrayList扩容原理——面试题

2020-07-21 04:09 1376 查看

下面,我们从源码来慢慢来刨析:
首先,我们来看看ArrayList类定义的源码:

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable

可以看到ArrayList继承了AbstractList类,以及其他的接口。
然后,我们来看看ArrayList里面的三个构造函数(此处着重分析前两个)

1.
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
2.
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

第一个构造函数是带参的,参数是容量大小,作用是在定义ArrayList时给定了初始数组大小,设为空数组;第二个构造函数是无参的,设置数组初始大小是10,空数组。注:调用默认的构造函数时数组初始化大小为0。
那么,我们再来看看,ArrayList扩容核心方法add:

public boolean add(E e) {//size为数组内元素的个数;容量为数组的长度
ensureCapacityInternal(size + 1);  // Increments modCount!!
elementData[size++] = e;
return true;
}

//确保数组扩容到指定大小
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;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

我们可以从add方法看到,ArrayList扩容分两步:
1.扩大容量
2.添加元素
add方法是主体,下面三个方法是为了实现扩容的。最后一个方法里调用了grow方法,那么下面我们来看看grow方法的定义:

private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
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);
}

可以看到,扩大以后的新的容量的计算方式:

旧的容量+旧容量的一半(>>右移运算符,相当于oldCapacity除以2的一次方),即扩大为旧容量的1.5倍;如果大于了最大数组大小,用最大数组处理(此处是调用的hugeCapacity方法)
我们可以看到扩容里重要的一步是:扩大容量之后,将原来的数组copy到扩大后的容量中,这里调用了copyOf方法。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: