欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ArrayList源码学习(2)

程序员文章站 2022-07-14 12:14:19
...

两个空数组常量属性

ArrayList源码学习(1)中详细描述了ArrayList的构造方法,但是并未对两个静态的空数组常量属性EMPTY_ELEMENTDATADEFAULTCAPACITY_EMPTY_ELEMENTDATA做说明,其实这两个属性,主要是为了在调用ArrayList对象的方法时,方便确定在创建当前对象时,调用了哪一种构造方法

  • 如果 elementDataDEFAULTCAPACITY_EMPTY_ELEMENTDATA ,则说明是调用了无参数的构造方法,所以初始容量是DEFAULT_CAPACITY

  • 如果 elementDataEMPTY_ELEMENTDATA ,说明是调用了有参数的构造方法,初始容量由构造方法的参数决定

添加元素

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

在创建了对象之后,就意味着我们可以用它在内存中存储数据,要往容器中添加数据,首先要确定顺序表中有足够的空间,而ensureCapacityInternal方法就是检测顺序表的容量,此时的参数是size+1,顺序表对象中元素个数为size,如果要成功向顺序表中添加一个元素,就必须要确保elementData的容量不得少于size+1,是顺序表中elementData的最小容量

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
 }

首先判断 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,表示当创建ArrayList对象时,调用的是无参构造方法,并且此时的顺序表中并无数据,所以从DEFAULT_CAPACITY和参数最小容量minCapacity 中获得最大值,进而确定一个明确的最小容量

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

ensureExplicitCapacity明确了顺序表的最小容量,modCount表示顺序表结构发生改变的次数,当顺序表的最小容量minCapacity大于elementData的长度时,对顺序表进行扩展。

private void grow(int minCapacity) {
    //获取elementData的现有长度
    int oldCapacity = elementData.length;
    //获取当前长度的1.5倍作为新的容量
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //如果新的容量小于最小容量,则以最小容量为新容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    //如果新的容量超过了最大容量,调用hugeCapacity进行容量检测
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    //将elementData中的元素复制到长度为newCapacity的新数组中,并将结果赋值给elementData
    elementData = Arrays.copyOf(elementData, newCapacity);
}

hugeCapacity方法是为了确保扩展的长度不会超过int类型的长度

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

minCapacity < 0,意味着扩展的容量已经超过了int类型的最大值,此时抛出了内存溢出的错误。当最小容量大于顺序表最大容量,就以Integer.MAX_VALUE为新容量,否则以MAX_ARRAY_SIZE为新容量