面试可能会聊到ArrayList的扩容机制:首次分配大小为10的一个容量,超过10的容量那么就会以1.5倍扩容
举个通俗的例子:你是个老板,最开始你有5个员工分别要住5个房间,ArrayList很大方,首次就直接分配10个房间给你。后来你的事业蒸蒸日上,你的员工越来越多,有11个员工了,住不下原来的10个房间,那么我ArrayList以原来已经住的房间(10个的房间)的1.5倍方式开房间给你员工住。
结合上面列子和下面的图,可能会让你更加深理解
(原来10个房间 × 1.5 = 15房间,15个房间 × 1.5 = 22房间)
代码实例
首先创建一个ArrayList,调用add,然后点击add方法里面的源码看看究竟吧!
ArrayList<String> arraylist = new ArrayList<String>();
arraylist.add("hello");
可以看到add的一个函数,它先调用ensureCapacityInternal,是不是不知道它是干啥的,从字面意思理解的话是确保容量足够的,再点击看它的源码
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
嗯…我去,又调了一个ensureExplicitCapacity,还有calculateCapacity,那就先看看
calculateCapacity
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
它会判断数组是否为空,如果为空,首次分配容量的值为10,它的常量:DEFAULT_CAPACITY = 10(这里确保容量足够)
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
接下来调用ensureExplicitCapacity,判断当数据大于当前数组,那么调用grow
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
实现扩容的方法正是:grow
主要gorw方法里这句,oldCapacity右移1(相当于除以2),再加上oldCapacity(可以理解就是1.5倍)赋值给newCapacity。如果扩展还是小于minCapacity,就扩展minCapacity
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity -minCapacity < 0)
newCapacity = minCapacity;
最后
你会发现看源码有点像剥洋葱,一层层的剥,不知道到什么时候你已经泪流满面了,当然只是个ArrayList还不至于啦