1. 程式人生 > >java集合之ArrayList源碼解讀

java集合之ArrayList源碼解讀

object類 util tcap div new length ext ali xtend

源自:jdk1.8.0_121
ArrayList繼承自AbstractList,實現了ListRandomAccessCloneableSerializable

變量

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

    // 空數組
    private static final Object[] EMPTY_ELEMENTDATA = {};

    // 默認空數組
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    // 存放數據的數組,被transient修飾的參數不會被序列化
transient Object[] elementData; // 實際元素的大小 private int size;

構造方法

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else
{ throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } public ArrayList(Collection<? extends E> c) { elementData = c.toArray
(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }

toArray()實現方式的不同

註:ArrayList(Collection<? extends E> c) 之所以要判斷是否為Object類型,是因為調用toArray()方法的實現方式不同。

java.util.ArrayList中,toArray()返回的是Object數組。

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

java.util.Arrays中,有個名為ArrayList的內部類,當調用Arrays.asList()時,返回的是java.util.Arrays$ArrayList內部類對象,而並非java.util.ArrayListjava.util.Arrays$ArrayList中的toArray()返回的雖然是Object數組,但是它的真實類型是個泛型數組。

    private final E[] a;

    public Object[] toArray() {
        return a.clone();
    }

ArrayList擴容

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

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

        ensureExplicitCapacity(minCapacity);
    }

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

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    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);
    }

從源碼可以看出,如果1.5倍的elementData.length小於10,會將elementData的大小擴容成默認的10,反之,則會以1.5倍的elementData.length進行擴容。

將elementData設置為實際容量,動態擴充的多余容量將被刪除

    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

java集合之ArrayList源碼解讀