Java的ArrayList(面试必须了解)——分析源码里的扩容机制(代码示例+图文)

面试可能会聊到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还不至于啦

猜你喜欢

转载自blog.csdn.net/A_hxy/article/details/105925587