1. 程式人生 > >JDK原始碼之集合

JDK原始碼之集合

一 初識

1,在這裡,集合類分為了Map和Collection兩個大的類別。

2,處於圖片左上角的那一塊灰色裡面的四個類(Dictionary、HashTable、Vector、Stack)都是執行緒安全的,可是它們都是JDK的老的遺留類。如今基本都不怎麼使用了,都有了相應的取代類。當中Map是用來取代圖片中左上角的那個Dictionary抽象類(Map的官方文件裡面有說明)。官方推薦使用Map介面來取代它。相同對於HashTable。官方推薦ConcurrentHashMap來取代。接著以下的Vector是List以下的一個實現類。

3,接著最上面的粉紅色部分是集合類全部介面關係圖。當中Map的結構比較簡單,而Collection的結構就相對複雜一些。Collection有三個繼承介面:List、Queue和Set

。接下來的綠色部分則是集合類的主要實現類了。這也是我們最常常使用的集合類了。

4,依照實現介面分類

實現Map介面的有:EnumMap、IdentityHashMap、HashMap、LinkedHashMap、WeakHashMap、TreeMap,
實現List介面的有:ArrayList、LinkedList
實現Set介面的有:HashSet、LinkedHashSet、TreeSet
實現Queue介面的有:PriorityQueue、LinkedList、ArrayQueue

5,依據底層實現的資料結構分類

底層以陣列的形式實現:EnumMap、ArrayList、ArrayQueue
底層以連結串列的形式實現:LinkedHashSet、LinkedList、LinkedHashMap
底層以hash table的形式實現:HashMap、HashSet、LinkedHashMap、LinkedHashSet、WeakHashMap、IdentityHashMap
底層以紅黑樹的形式實現:TreeMap、TreeSet
底層以二叉堆的形式實現:PriorityQueue

6,最下方的一個整塊都是java.util.concurrent包裡面的類,依照包名我們就能夠知道這個包裡面的類都是用來處理Java程式設計中各種併發場景的。

7,下面這張圖,是常用的集合的基本特性:

8,Hashtable VS HashMap

  • Hashtable是執行緒安全的,它的每個方法中都加入了Synchronize方法。在多執行緒併發的環境下,可以直接使用Hashtable,不需要自己為它的方法實現同步
  • HashMap不是執行緒安全的,在多執行緒併發的環境下,可能會產生死鎖等問題。多執行緒環境下使用HashMap時就必須要自己增加同步處理
  • 雖然HashMap不是執行緒安全的,但是它的效率會比Hashtable要好很多
    。這樣設計是合理的。在我們的日常使用當中,大部分時間是單執行緒操作的。HashMap把這部分操作解放出來了。當需要多執行緒操作的時候可以使用執行緒安全的ConcurrentHashMap。ConcurrentHashMap雖然也是執行緒安全的,但是它的效率比Hashtable要高好多倍。因為ConcurrentHashMap使用了分段鎖,並不對整個資料進行鎖定

9,ArrayList VS LinkedList

  • ArrayList是實現了基於動態陣列的資料結構,LinkedList基於連結串列的資料結構。 
  • 對於隨機訪問get和set,ArrayList覺得優於LinkedList,因為LinkedList要移動指標。 
  • 對於新增和刪除操作add和remove,LinedList比較佔優勢,因為ArrayList要移動資料。

二 Collection

1,本質上來說,資料結構,實際上是設計一種容器,而容器的特性大體包括如下:

  • 容器中如何進行儲存
  • 容器中的資料如何獲取
  • 容器中的資料如何新增  
  • 容器中的資料如何遍歷
  • 器中的資料如何搜尋
  • 容器中的其他特性(判空,替換,排序,溢位,併發,同步,拆分,匯聚等等)

    Collection是容器的框架集,其中包含了我們經常使用的容器.

2,原始碼分析

public interface Collection<E> extends Iterable<E> {
    // Query Operations    原註釋,不明意義

    //定義size方法,應返回size大小,最大值為Integer.MAX_VALUE
    int size();

    //定義isEmpty方法,用於返回是否為空
    boolean isEmpty();

    //定義contains方法,判斷一個obj是否屬於此集合
    boolean contains(Object o);

    //定義迭代器方法,返回一個迭代器物件
    Iterator<E> iterator();

    //定義轉換為轉換Obj陣列的方法,返回一個obj陣列
    Object[] toArray();

    //定義轉換為泛型T陣列的方法,返回一個指定泛型的陣列
    <T> T[] toArray(T[] a);

    //定義add方法,新增一個元素e,並返回新增成功標誌
    boolean add(E e);

    //定義remove方法,移除一個元素obj,並返回移除元素成功標誌
    boolean remove(Object o);

    //定義containsAll方法,判斷是否包含集合例項物件c
    boolean containsAll(Collection<?> c);

    //定義addAll方法,新增集合例項物件c到本例項中
    boolean addAll(Collection<? extends E> c);

    //定義removeAll方法,從本例項中移除集合實力物件c
    boolean removeAll(Collection<?> c);


    /**
     * jdk8新增
     * 大意為:
     * 定義removeIf方法,該方傳遞引數為函式式,傳遞內容是一個介面型別,該介面型別
     * 定義為一個filter函式,該函式用於傳遞給Objects.requireNonNull判斷,然後呼叫
     * 迭代器,將滿足該定義的filter的本例項中的元素移除
     * @since 1.8
     */
    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }

    //定義retainAll方法,取本例與集合例項c的交集,判斷交集元素數量是否大於0
    boolean retainAll(Collection<?> c);

    //定義clear方法,清除本例集合中的所有元素
    void clear();

    // Comparison and hashing    原註釋,不明意義

    //不解釋
    boolean equals(Object o);

    //定義hashCode方法,獲取hashCode標記的方法
    int hashCode();

    /**
     *jdk8新增
     *大意為:
     *將迭代器拆分,重寫自Iterable介面,從已知元素數量的本例中返回拆分後的迭代器
     *此方法返回的為本類本身
     *子類可能重寫迭代器拆分,將一個集合的迭代拆分為多個集合的迭代交由多個執行緒
     * @since 1.8
     */
    @Override//重寫父類
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }

    /**
     * jdk8新增
     * 大意為:
     * 將預設的迭代器拆分後的結果,聚合為流,該流並非io中的流,
     * 是一種類似於資料排序操作流
     * @since 1.8
     */
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }

    /**
     * jdk8新增
     * 同上,但是具體其他的實現中,因為可並行,所以可能是執行緒不安全的
     * 
     * @since 1.8
     */
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }

Oracle已經開始向介面中引入預設方法和靜態方法,以此來減少抽象類和介面之間的差異。現在,我們可以為介面提供預設實現的方法了並且不用強制子類來實現它。如上方法前有default標識的方法,子類可不必實現(JDK1.8)

集合作為容器,其體系中的所有集合都包括了:

大小(size),判空(isEmpty),新增元素(add),刪除元素(remove),是否包含(contains),轉換陣列(toArray),清空(clear),遍歷與迭代(forEach(父介面中),iterator),是否相同(equals),雜湊(hashCode),求交集(retainAll)
除此之外,提供了java8的分離介面,聚合介面,為了大容量集合的多執行緒操作