本人,小白中的小白,今天经历一场前所未有的面试,深受刺激,决定动手写文章,对所学内容进行输出。文章比较适合小白阅读还有希望高人指点。
这是我第一次写博客请大牛们多多指教,多多包容!

面试中提问到一个关于ArrayList的问题。谁都知道ArrayList底层是数组,并且会自动扩容。那面试官就问了,ArrayList是怎么扩容的?什么时候它会进行扩容?扩容多少?


文章目录

  • 初始化 以及 扩容问题


初始化 以及 扩容问题

既然是扩容问题,二话不说,先看ArrayList源码。(扩容有关的方法)

private Object[] grow(int minCapacity) {
        return this.elementData = Arrays.copyOf(this.elementData,this.newCapacity(minCapacity));		   
    }

扩容嘛,当然是看grow方法,里面一个Arrays.copyOf方法即数组复制,就是创建一个新的数组长度为this.newCapacity(minCapacity),把老数组里面的内容复制到新数组中。
看copyOf方法的第二个参数,这个参数是int类型,就是新数组的长度。this.newCapacity(minCapacity)即调用自己的newCapacity方法,传递的参数是minCapacity,这个参数是添加元素到末尾之后的容量,即保证list中含有的最小容量minCapacity
以上代码需明确:
扩容就是复制数组,就是创建一个新的数组,然后把老数组的内容复制进新数组中。至于新的数组长度多少,全在newCapacity方法里面揭晓!
.

private int newCapacity(int minCapacity) {
    //这里就是获取老数组的长度
        int oldCapacity = this.elementData.length;
        //这里就是扩容的关键代码。将数组长度增加原来的0.5倍!
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //扩充之后,还是小于minCapacity即:还是小于数组添加新元素之后所需的最小容量
        if (newCapacity - minCapacity <= 0) {
            if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                return Math.max(10, minCapacity);
            } else if (minCapacity < 0) {
                throw new OutOfMemoryError();
            } else {
            //还是小于minCapacity,那就minCapacity实际元素的个数,进行扩容。
                return minCapacity;
            }
        } else {
            return newCapacity - 2147483639 <= 0 ? newCapacity : hugeCapacity(minCapacity);
        }
    }

对上述代码简单描述:

  1. 明确该方法的作用,就是返回新数组的长度是多少。
  2. 数组一般是怎么扩容 oldCapacity + (oldCapacity >> 1)。直白点说就是:老数组长度+老数组长度的一半
  3. 当数组扩大了老数组的百分之50之后,有可能还是不够用,即newCapacity - minCapacity <= 0
    此时分为两种情况讨论(要么老数组本来就是空的,要么就是扩容之后容量还是不够

情况一:此时就为数组建立一个空数组

this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA

并且,为它创建一个初始容量大小为10的数组,或者如果所需的容量超过10那就以minCapacity为标准来创建大小(注意:该方法返回的是新数组长度的大小,要么返回10要么返回minCapacity)

return Math.max(10, minCapacity)

  1. 如果数组不为空,当然就是扩容后小于实际容量大小那就按照数组的实际容量return minCapacity
  2. 数组扩容之后,也满足了实际容量大小了。为什么不直接return newCapacity返回新长度呢。而是还要和2147483639这个数比较大小,如果超过了这个21374…这个数,那就返回hugeCapacity(minCapacity)。那我得看看这个方法,究竟是何方神圣!

return newCapacity - 2147483639 <= 0 ? newCapacity : hugeCapacity(minCapacity);

.

其实就那样啦,如果实际的容量大于了2147483639这个数,那就返回 2147483647。没啥没啥,不必惊讶

return minCapacity > 2147483639 ? 2147483647 : 2147483639

private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) {
            throw new OutOfMemoryError();
        } else {
            return minCapacity > 2147483639 ? 2147483647 : 2147483639;
        }
    }

总结数组扩容的过程:
1、如果数组为空的话,初始容量大小为10的数组,如果10不够用那就用实际容量大小
2、一般扩容,是增大原来数组的一半,如果不够用,那就用实际容量大小