關於ArrayList經驗分享(源碼分析)

集合的作用就是以一定的方式組織,存儲數據。對於ArrayList,我認爲需要的關注以下內容:
 1.集合的基本存儲單元
 2.集合的增刪改查基本操作的實現
 3.存儲數據的要求,是否爲空,是否允許重複
 4.存放與讀取是否有序
 5.是否線程安全

基本存儲單元

 ArrayList的源碼片段:

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; // non-private to simplify nested class access
private int size;

底層存放的是Object[]數組,size不是數組長度,單獨計算。

集合的增刪改查基本操作的實現

1.新增元素

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
 }
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);
}

ensureCapacityInternal方法用於判斷數組是否需要擴容,底層調用grow方法繼續數組動態擴容,上面代碼擴容了1.5倍的長度。Arrays.copyOf方法會先創建一個長度爲newCapacity的數據,調用System.arraycopy將原先的elementData數據拷貝至新的數組中,這是順序插入的實現。

    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

這是中間插入的實現,先判斷數組容量是否足夠,之後從index位置開始,利用System.arraycopy做一個整體的數據複製並向後位移一個位置,將需要插入的元素放置在index位置。如果集合中的數據比較龐大,而且需要的插入前半部分操作比較多,ArrayList的效率會很低。

2.修改元素

public E set(int index, E element) {
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
比較簡單,不詳細說明。

3.刪除元素

    public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

刪除方法和中間插入的實現差不多,System.arraycopy將數組從index位置複製並向前位移一個單位,完成後將最後一個元素置爲null。

存儲數據的要求,是否爲空,是否允許重複

允許爲空或者null,允許重複

存放與讀取是否有序

底層實現是數組,所以有序

是否線程安全

非線程安全,因爲所有方法都是不同步的。如果需要線程安全,可以使用Vector,Vector裏的實現基本和ArrayList一致,每個方法都加入了synchronized,不同的地方是Vector多了一個增長因子capacityIncrement,數組擴容的時候回用到。

ArrayList的優缺點

優點:查找速度快,順序插入速度快,缺點:刪除和中間插入用到了數組拷貝,會影響性能。

適用場景:訪問比較頻繁,順序插入比較多的場景。





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