美文网首页程序员
ArrayList源码学习(2)

ArrayList源码学习(2)

作者: 心扬 | 来源:发表于2017-10-28 23:31 被阅读0次

两个空数组常量属性

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为新容量

相关文章

网友评论

    本文标题:ArrayList源码学习(2)

    本文链接:https://www.haomeiwen.com/subject/hhnspxtx.html