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要好很多
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的分離介面,聚合介面,為了大容量集合的多執行緒操作