ArrayList創建新集合源碼剖析

ArrayList簡介

      ArrayList的頂層是數組隊列,相當於動態數組。與數組相比,數組的長度是固定不可變的,但集合可以動態擴容。在添加大量元素前,應用程序可以使用ensureCapacity()方法來操作增加當前集合的容量,這樣可以堅持少遞增式再分配數量。ArrayList繼承於AbstractList,實現了 List, RandomAccess, Cloneable, java.io.Serializable 這些接口。

ArrayList創建新集合

  1. 創建一個空ArrayList集合的時候,源碼中會調用一個默認的空數組創建該集合,源碼:this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA ,而elementData定義的是個Object[ ],而DEFAULTCAPACITY_EMPTY_ELEMENTDATA則直接定義爲{}空的數組,初始的ArrayList集合是沒有長度的
  2. 空集合的長度是0,只有當往空集合中使用add()方法添加元素的時候,纔會進行擴容
    源碼:public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }   add()方法中先調用了 ensureCapacityInternal(size + 1)方法,此時的size則是0,傳入的參數即1,我們再看看ensureCapacityInternal()方法的源碼:
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }這個方法中調用的ensureExplicitCapacity()方法就是ArrayList的核心方法,得到最小的擴容量,該方法中調用了calculateCapacity()方法,源碼:
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    },判斷了當前集合是不是一個空集合,如果是,則在默認集合大小和最小擴容大小和需要的最小長度中取最大的擴容量,我的理解是ArrayList如果元素小於10則只在第一次進行擴容,後面大於默認長度的時候則會根據每次計算的擴容需要的量來進行擴容。
    ensureExplicitCapacity的源碼:
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
    
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }當拿到擴容量計算值之後和當前集合長度相比,如果擴容長度大於當前長度,那麼就調用grow()方法進行擴容,否則不需要擴容
  3. 使用帶參構造方法創建ArrayList的時候,參數爲int類型的值,源碼中會判斷該參數的值,先看下源碼:
  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);
    }
},當傳入的參數大於0的時候,那麼會創建一個指定大小的數組創建集合,如果傳入的參數=0,那麼就會創建一個空的數組創建集合,如果傳入負數,想當然會報錯,因爲數組長度沒有負數。

    4.使用帶參構造方法創建ArrayList的時候,參數爲另外一個集合,源碼中會判斷該參數的值,先看下源碼: 

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()方法將該集合轉爲數組,判斷轉換後的集合長度是否等於0,如果不等於0,
且參數類型不是object[].class相等,那麼會中用數組的copyOf方法拷貝一個參數傳遞的數組,類型設置爲object[].class。如果轉換後的集合長度是否等於0,那麼就直接創建一個空的數組作爲集合保存數據。

突然看到集合方面到問題,也沒有詳細看過源碼,對於集合到創建不瞭解,今天沒事就把自己理解的東西寫出來,有什麼錯誤的,希望大牛指出來,加以改正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章