JDK源碼走讀(3):容器之ArrayList

本章分析List系列中的ArrayList,有些與PriorityQueue類似,比如底層同樣採取數組存儲元素,也涉及到擴容操作等;也有不同之處,比如PriorityQueue不允許存入的元素爲null,而ArrayList允許將null元素存放其中。

一、 類實現/繼承體系結構

爲了對整個List實現/繼承體系有個全貌,先將體系結構圖畫出來:

二、 關鍵數據成員

(1)存儲結構

transient Object[]elementData; // non-private to simplify nested class access;

以數組作爲底層存儲結構,存放ArrayList鏈表中的元素

數組elementData的默認初始化大小(DEFAULT_CAPACITY)是10。

(2)數組存放的元素個數

private int size;

三、 構造函數

ArrayList提供了多種形式的構造函數,在此不一一列舉,就參數來說,主要包括,數組鏈表(elementData)初始化大小(initialCapacity)值、其他集合

這裏要講下以下幾個構造函數:

publicArrayList (Collection<? extends E> c):利用另一個集合初始化ArrayList,要求就是負責初始化集合中的元素類型是E或者是E的子類。

四、 一些鏈表操作

(1)  void trimToSize():將ArrayList的存儲空間壓縮到size大小,將空閒空間還給系統

做法就是Arrays.copyOf(elementData, size)新生成一個數組,賦值給elementData;

(2)  void sort(Comparator<? super E> c):對鏈表進行排序,調用了Arrays.sort接口

Arrays.sort((E[])elementData, 0, size, c);

這裏有一點,因爲ArrayList接口都不是線程安全的,在一個線程操作鏈表時,並不能防止其他線程也在操作鏈表,有可能在排序時,其他線程已經修改了鏈表,修改有可能導致排序結果不準確,所以,這時就需要拋出異常:

public void sort(Comparator<?super E> c) {

    final int expectedModCount = modCount;

    Arrays.sort((E[]) elementData, 0, size, c);

    if (modCount != expectedModCount) {

            throw newConcurrentModificationException();

        }

        modCount++;

    }

五、 增

(1)  boolean addAll(Collection<? extends E> c):將容器c中元素添加到ArrayList的末尾

首先檢查容量capacity,然後執行拷貝

        Object[] a = c.toArray();

        int numNew = a.length;

        ensureCapacityInternal(size +numNew);  // Increments modCount

        System.arraycopy(a, 0, elementData,size, numNew);

        size += numNew; 

System.arraycopy參數含義:

第一個參數:數據來源數組;

第二個參數:數據來源數組的起始拷貝索引index;

第三個參數:數據目標數組;

第四個參數:數據目標數組起始拷貝索引index;

第五個參數:拷貝元素的個數;

(2)  boolean addAll(int index, Collection<?extends E> c):將容器c中元素添加到ArrayList中,添加的起始位置是在index處

如果index不是數組末尾,就涉及到兩次拷貝:

if (size - index > 0)
    System.arraycopy(elementData,index, elementData, index+numNew, numMoved);                          
    System.arraycopy(a,0, elementData, index, numNew);

六、 刪

(1)  E remove(int index):刪除位於index位置的元素

不可避免的,會將數組elementData 在index之後元素前移一個位置,複雜度O(n)

System.arraycopy(elementData,index+1, elementData, index, numMoved);

(2)  boolean removeAll(Collection<?> c):刪除ArrayList中的集合c中的元素,即求交集

這裏使用了一個叫做batchRemove的私有函數:

    private booleanbatchRemove(Collection<?> c, boolean complement) {

        final Object[] elementData =this.elementData;

        int r = 0, w = 0;

        boolean modified = false;

        try {

            for (; r < size; r++)

                if (c.contains(elementData[r])== complement)

                    elementData[w++] =elementData[r];

        } finally {

            // Preserve behavioralcompatibility with AbstractCollection,

            // even if c.contains() throws.

            if (r != size) {

                System.arraycopy(elementData,r,

                                 elementData,w,

                                 size - r);

                w += size - r;

            }

            if (w != size) {

                // clear to let GC do its work

                for (int i = w; i < size;i++)

                    elementData[i] = null;

                modCount += size - w;

                size = w;

                modified = true;

            }

        }

        return modified;

    }

七、 改

八、 查

peek():返回隊列queue中index=0的元素,queue[0];如果爲空,則返回null。

contains(Object o):

public booleancontains(Object o) {

        return indexOf(o) != -1;

}

九、 遍歷

ArrayList實現了內部類Itr:

private class Itrimplements Iterator<E>

ArrayList還實現了內部類ListItr,其繼承自Itr,並實現了接口ListIterator:

private class ListItrextends Itr implements ListIterator<E>

而接口ListIterator繼承自Iterator接口:interface ListIterator<E>extends Iterator<E>

所以,可以通過兩種迭代器遍歷ArrayList,分別對應到Itr和ListItr:

Iterator<String>iter = names.iterator();

ListIterator<String>iter = names.listIterator()/names.listIterator(1);

 Itr就是通用的迭代器,提供hasNext和next接口:

public Iterator<E> iterator() {

        return new Itr();

}

ListIterator針對ArrayList,除了提供hasNext和next接口,還提供遍歷的起始點index,並且還可以逆序遍歷:

   public ListIterator<E> listIterator()/listIterator(index) {
        return new ListItr(0)/ListItr(index);
   }
   ListIterator<String> iter = names.listIterator(3);
   while (iter.hasPrevious()) {
      System.out.println(iter.previous());
   }

十、 子鏈表subList

ArrayList實現了List<E>subList(int fromIndex, int toIndex)

List<E>subList(int fromIndex, int toIndex)接口即返回一個新生成的子鏈表subList對象。

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