ArrayList的源码分析(基于jdk1.8)

1.初始化

transient Object[] elementData;  //实际存储元素的数组

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

public ArrayList() {
    //初始化为一个默认的空数组
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

2. 添加元素

private static final int DEFAULT_CAPACITY = 10;//默认容量

public boolean add(E e) {
    //确保当前数组的容量是够得
    ensureCapacityInternal(size + 1);  // Increments modCount!!

    //将新元素添加到[size++]的位置
    elementData[size++] = e;
    return true;
}
private void ensureCapacityInternal(int minCapacity) { //如果是第一次添加 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {   //扩容为默认容量大小:10   minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } //每一次添加都要判断是否需要扩容 ensureExplicitCapacity(minCapacity); }

3.扩容

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

    // 如果需要扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) {
    // 先获取当前数组的容量
    int oldCapacity = elementData.length;

    //新容量为当前容量 + 当前容量的一半
    int newCapacity = oldCapacity + (oldCapacity >> 1);

    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);

    // 拷贝原数组中的元素至新数组,并返回新数组的引用
    elementData = Arrays.copyOf(elementData, newCapacity);
}

4.结论

  ArrayList物理结构是数组,决定了它的存储特点是:需要开辟连续的存储空间来存储元素,当存储容量不够时,需要扩容,增加容量为原来的1.5倍。类似的,Vector的物理结构也是数组,当存储容量不够时,需要扩容为原来的2倍。那么是1.5倍好呢?还是2倍好呢?1.5倍使得数组空间使用率提高了,但是这也增加了扩容的频率。所以,建议大家在选择动态数组时,如果对要存储的元素个数有一个预估时,那么可以在创建ArrayList时,就使用ArrayList(int initialCapacity) 构造器,避免反复扩容。

猜你喜欢

转载自www.cnblogs.com/duoduotouhenying/p/10136406.html