ArrayList中add()方法过程源码分析(扩容机制)

ArrayList集合底层原理

① 利用空参创建的集合,在底层创建一个默认长度为0的数组

② 添加第一个元素时,底层会创建一个新的长度为10的数组

③ 存满时,会扩容1.5倍

④ 如果依次添加多个元素,1.5倍还放不下.则新创建数组的长度以实际为准

此次为添加第一次元素

ArrayList list = new ArrayList<>(); // 默认初始长度为0
list.add("aaa");  // 添加第一个元素

以下为ArrayList底层源码

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

private static final int DEFAULT_CAPACITY = 10;

transient Object[] elementData;
 
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

当在调用ArrayList无参构造方法时,会创建一个空的数组.其初始长度默认为0.

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // size目前为0
        elementData[size++] = e;
        return true;
    }

 在调用ArrayList的add方法后,传入的参数为添加的数据(这里以"aaa"为例),add方法会调用其内部的ensureCapacityInternal方法,并传入参数1(size+1)

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        // 若数组等于空数组,返回DEFAULT_CAPACITY和minCapacity中的较大的数
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // 此时的minCapacity为10,elementData.length为0
        if (minCapacity - elementData.length > 0)
            grow(minCapacity); // 扩容方法
    }

    private void grow(int minCapacity) {
       // minCapacity为10
        int oldCapacity = elementData.length;   //0
        int newCapacity = oldCapacity + (oldCapacity >> 1);  //0
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;  //10
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
calculateCapacity方法返回DEFAULT_CAPACITY(10),并调用ensureExplicitCapacity方法,参数为10,ensureExplicitCapacity方法中进行判断,条件成立,调用grow方法,传入参数10.方法中进行判断,条件成立,将minCapacity(10)赋值给newCapacity.最后调用Arrays.copyOf方法复制elementData数组的数据以长度为10赋值给elementData.此时的elementData是一个长度为10的空数组.再回到add方法中,elementData[size++]=e;  将数据加进数组.

此次为添加第11个元素

list.add("kkk");  // 添加第十一个元素
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // size目前为10
        elementData[size++] = e;
        return true;
    }

在调用ArrayList的add方法后,传入的参数为添加的数据(这里以"kkk"为例),add方法会调用其内部的ensureCapacityInternal方法,并传入参数11(size+1)

    private void ensureCapacityInternal(int minCapacity) {
        // 这里的minCapacity为11
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        // 返回11
        return minCapacity;
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // elementData.length为10
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    private void grow(int minCapacity) {
        // minCapacity为11
        int oldCapacity = elementData.length;  //10
        int newCapacity = oldCapacity + (oldCapacity >> 1);  // 15
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

calculateCapacity方法返回11,并调用ensureExplicitCapacity方法,参数为11,ensureExplicitCapacity方法中进行判断,条件成立,调用grow方法,传入参数11.方法中进行判断,条件不成立,最后调用Arrays.copyOf方法复制elementData数组的数据以长度为15赋值给elementData.此时已完成扩容整个过程.再回到add方法中,elementData[size++]=e; 将数据加进数组.

此次为添加另一个整个list

list1.addAll(list2); // 假设list1容量刚好为10,list2容量为100

调用方法addAll并传入参数list2 

    public boolean addAll(Collection c) {
        Object[] a = c.toArray();
        int numNew = a.length;  // 100
        // size此时为10
        ensureCapacityInternal(size + numNew);  
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

方法中调用ensureCapacityInternal 方法并闯入参数110(size+numNew)

    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; // 110
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // minCapacity 为110,elementData.length为10
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    private void grow(int minCapacity) {
        int oldCapacity = elementData.length; // 10
        int newCapacity = oldCapacity + (oldCapacity >> 1); //15
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity; //110
        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);
    }

calculateCapacity方法返回110,并调用ensureExplicitCapacity方法,参数为110,ensureExplicitCapacity方法中进行判断,条件成立,调用grow方法,传入参数110.方法中进行判断,条件成立,将minCapacity(110)赋值给newCapacity.最后调用Arrays.copyOf方法复制elementData数组的数据以长度为110赋值给elementData.此时已完成扩容整个过程.再回到add方法中,System.arraycopy(a, 0, elementData, size, numNew);将数据加进原来的数组.

你可能感兴趣的:(数据结构)