JDK源码阅读 0901 - 集合ArrayList

public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable
/**
实现使用的标记接口表示*它们支持快速(通常为恒定时间)随机访问。该接口的主要目的是允许通用算法更改其行为,以便在应用于随机访问或顺序访问列表时提供良好的性能
*/
public interface RandomAccess {
}  

不得不说,阅读源码前去参考一遍注释会让自己能有一个明确的思路,甚至明白一些自己写出的bug原因。
ArrayList 被解释为List接口的可调整大小的数组实现。大致来说其中所有的操作都是线性运行的,于LinkList实现的常量相比,常量因子较低。每个 ArrayList实例都有一个容量。容量是*用于在列表中存储元素的数组的大小。它总是至少等于列表大小。随着元素被添加到ArrayList中,其容量会自动增长。除了添加元素具有固定的摊销时间成本外,没有指定增长策略的细节。
我理解上述问题,即为ArrayList 增长策略只是单个根据元素插入个数确定要增加的容量,稍等测试,可以调用ensureCapacity()方法进行大量数据插入前的扩容。但是方法未实现同步,多个线程同时访问如果修改需同步至外部。否则会被覆盖。

//默认容量为10
private static final int DEFAULT_CAPACITY = 10;
// 缩小当前实例的大小 等于 当前实例的实际大小  实例的容量调整为列表的当前大小。
 public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

Arraylist 扩展容量的方法在add()/addAll()发给发时候回进行调用,首先确认(当前容量+1)是否能够容纳下原数组与新增的实体数量,不能就在原容量基础上扩大两倍,仍不够就使用最大容量。

// add() 默认追加到当前list 最后的位置
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
// add() 都需要先确认当前数组的容量 然后进行插入 addAll进行数组拷贝进行插入 size为当前数组list 的容量属性 初始化已经赋值 且特殊操作进行更新
public boolean addAll(Collection c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

  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;
    }
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
// elementData 为当前数组list 中的所有元素

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

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

其上代码 可以看到一个扩容的链路调用。

前几天,需要使用到List与数组Array 之间的转换,这里其实使用到的还是java.util.Arrays 的拷贝方法

public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

快速失败 比较 modcount 在 Abstractlist 中有详细代码

你可能感兴趣的:(JDK源码阅读 0901 - 集合ArrayList)