1. 程式人生 > >JAVA中的集合原始碼分析一:ArrayList的內部實現原理

JAVA中的集合原始碼分析一:ArrayList的內部實現原理

作為以java為語言開發的android開發者,集合幾乎天天都要打交道,無論是使用頻率最高的ArrayList還是HashSet,都頻繁的出現在平時的工作中。但是其中的原理之前卻一直沒深入探究,接下來記錄一下這次自己學習ArrayList原始碼的過程。

一.構造方法:

 private static final int DEFAULT_CAPACITY = 10;//預設陣列長度
 transient Object[] elementData;   //空陣列
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //預設空陣列
    private static final Object[] EMPTY_ELEMENTDATA = {}; //空陣列

/**
*建立一個空陣列
*/
 public ArrayList() {
     this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
 }


/**
*建立一個長度為輸入長度initialCapacity的一個數組
*/
 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);
        }
    }

首先看構造方法,其實構造方法很簡單,就是建立一個數組。顧名思義,arraylist底層其實就是以陣列進行實現的,普通的構造方法List list = new ArrayList();實現的就是建立一個空陣列。而帶引數的構造方法則是建立一個長度為輸入長度的陣列。

二.add方法:

    //新增一個子項
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 對陣列進行擴容判斷
        elementData[size++] = e;
        return true;
    }

   private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, 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);  //經過激烈的大小比較,獲取到一個新陣列
    }

add運算需要對當前的陣列容量進行比較,如果大於當前容量,需要通過移位運算進行擴容,隨後再把原先的陣列複製到新陣列中,最後再新增新元素。

三.remove方法:

    public boolean remove(Object o) {
        if (o == null) { //對元素是否為空進行單獨判斷
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index); //找到指定元素跳轉到刪除的方法
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1; //獲取到需要刪除的陣列下標
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);//將刪除位置後面的元素集體複製到需要刪除的位置,也就是說將numMoved後面的所有元素整體前移一位。
        elementData[--size] = null; // clear to let GC do its work
    }

remove方法是比較方便理解的,就是通過for迴圈找到需要刪除的位置,然後再通過陣列的前移來將需要刪除的元素移除,表面上是刪除了某個元素,實際上是將它後面的所有元素往前移動了一位,最後將size減一,並且置空最後一個元素。

四.clear方法

  public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

這個沒什麼好說的,也就是通過for迴圈將陣列中每個元素置空。