死磕 java集合之終結篇

彤哥讀原始碼發表於2019-05-04

概覽

我們先來看一看java中所有集合的類關係圖。

collection1

這裡面的類太多了,請放大看,如果放大還看不清,請再放大看,如果還是看不清,請放棄。

我們下面主要分成五個部分來逐個擊破。

List

List中的元素是有序的、可重複的,主要實現方式有動態陣列和連結串列。

List

java中提供的List的實現主要有ArrayList、LinkedList、CopyOnWriteArrayList,另外還有兩個古老的類Vector和Stack。

關於List相關的問題主要有:

(1)ArrayList和LinkedList有什麼區別?

(2)ArrayList是怎麼擴容的?

(3)ArrayList插入、刪除、查詢元素的時間複雜度各是多少?

(4)怎麼求兩個集合的並集、交集、差集?

(5)ArrayList是怎麼實現序列化和反序列化的?

(6)集合的方法toArray()有什麼問題?

(7)什麼是fail-fast?

(8)LinkedList是單連結串列還是雙連結串列實現的?

(9)LinkedList除了作為List還有什麼用處?

(10)LinkedList插入、刪除、查詢元素的時間複雜度各是多少?

(11)什麼是隨機訪問?

(12)哪些集合支援隨機訪問?他們都有哪些共性?

(13)CopyOnWriteArrayList是怎麼保證併發安全的?

(14)CopyOnWriteArrayList的實現採用了什麼思想?

(15)CopyOnWriteArrayList是不是強一致性的?

(16)CopyOnWriteArrayList適用於什麼樣的場景?

(17)CopyOnWriteArrayList插入、刪除、查詢元素的時間複雜度各是多少?

(18)CopyOnWriteArrayList為什麼沒有size屬性?

(19)比較古老的集合Vector和Stack有什麼缺陷?

關於List的問題大概就這麼多,你都能回答上來嗎?

點選下面連結可以直接到相應的章節檢視:

死磕 Java集合之ArrayList原始碼分析

死磕 java集合之LinkedList原始碼分析

死磕 java集合之CopyOnWriteArrayList原始碼分析

Map

Map是一種(key/value)的對映結構,其它語言裡可能稱作字典(Dictionary),包括java早期也是叫做字典,Map中的元素是一個key只能對應一個value,不能存在重複的key。

Map

java中提供的Map的實現主要有HashMap、LinkedHashMap、WeakHashMap、TreeMap、ConcurrentHashMap、ConcurrentSkipListMap,另外還有兩個比較古老的Map實現HashTable和Properties。

關於Map的問題主要有:

(1)什麼是雜湊表?

(2)怎麼實現一個雜湊表?

(3)java中HashMap實現方式的演進?

(4)HashMap的容量有什麼特點?

(5)HashMap是怎麼進行擴容的?

(6)HashMap中的元素是否是有序的?

(7)HashMap何時進行樹化?何時進行反樹化?

(8)HashMap是怎麼進行縮容的?

(9)HashMap插入、刪除、查詢元素的時間複雜度各是多少?

(10)HashMap中的紅黑樹實現部分可以用其它資料結構代替嗎?

(11)LinkedHashMap是怎麼實現的?

(12)LinkedHashMap是有序的嗎?怎麼個有序法?

(13)LinkedHashMap如何實現LRU快取淘汰策略?

(14)WeakHashMap使用的資料結構?

(15)WeakHashMap具有什麼特性?

(16)WeakHashMap通常用來做什麼?

(17)WeakHashMap使用String作為key是需要注意些什麼?為什麼?

(18)什麼是弱引用?

(19)紅黑樹具有哪些特性?

(20)TreeMap就有序的嗎?怎麼個有序法?

(21)TreeMap是否需要擴容?

(22)什麼是左旋?什麼是右旋?

(23)紅黑樹怎麼插入元素?

(24)紅黑樹怎麼刪除元素?

(25)為什麼要進行平衡?

(26)如何實現紅黑樹的遍歷?

(27)TreeMap中是怎麼遍歷的?

(28)TreeMap插入、刪除、查詢元素的時間複雜度各是多少?

(29)HashMap在多執行緒環境中什麼時候會出現問題?

(30)ConcurrentHashMap的儲存結構?

(31)ConcurrentHashMap是怎麼保證併發安全的?

(32)ConcurrentHashMap是怎麼擴容的?

(33)ConcurrentHashMap的size()方法的實現知多少?

(34)ConcurrentHashMap是強一致性的嗎?

(35)ConcurrentHashMap不能解決什麼問題?

(36)ConcurrentHashMap中哪些地方運用到分段鎖的思想?

(37)什麼是偽共享?怎麼避免偽共享?

(38)什麼是跳錶?

(40)ConcurrentSkipList是有序的嗎?

(41)ConcurrentSkipList是如何保證執行緒安全的?

(42)ConcurrentSkipList插入、刪除、查詢元素的時間複雜度各是多少?

(43)ConcurrentSkipList的索引具有什麼特性?

(44)為什麼Redis選擇使用跳錶而不是紅黑樹來實現有序集合?

關於Map的問題大概就這麼多,你都能回答上來嗎?

點選下面連結可以直接到相應的章節檢視:

死磕 java集合之HashMap原始碼分析

死磕 java集合之LinkedHashMap原始碼分析

死磕 java集合之WeakHashMap原始碼分析

死磕 java集合之TreeMap原始碼分析(一)

死磕 java集合之TreeMap原始碼分析(二)

死磕 java集合之TreeMap原始碼分析(三)

死磕 java集合之TreeMap原始碼分析(四)

死磕 java集合之ConcurrentHashMap原始碼分析(一)

死磕 java集合之ConcurrentHashMap原始碼分析(二)

死磕 java集合之ConcurrentHashMap原始碼分析(三)

死磕 java集合之ConcurrentSkipListMap原始碼分析

Set

java裡面的Set對應於數學概念上的集合,裡面的元素是不可重複的,通常使用Map或者List來實現。

Set

java中提供的Set的實現主要有HashSet、LinkedHashSet、TreeSet、CopyOnWriteArraySet、ConcurrentSkipSet。

關於Set的問題主要有:

(1)HashSet怎麼保證新增元素不重複?

(2)HashSet是有序的嗎?

(3)HashSet是否允許null元素?

(4)Set是否有get()方法?

(5)LinkedHashSet是有序的嗎?怎麼個有序法?

(6)LinkedHashSet支援按元素訪問順序排序嗎?

(8)TreeSet真的是使用TreeMap來儲存元素的嗎?

(9)TreeSet是有序的嗎?怎麼個有序法?

(10)TreeSet和LinkedHashSet有何不同?

(11)TreeSet和SortedSet有什麼區別和聯絡?

(12)CopyOnWriteArraySet是用Map實現的嗎?

(13)CopyOnWriteArraySet是有序的嗎?怎麼個有序法?

(14)CopyOnWriteArraySet怎麼保證併發安全?

(15)CopyOnWriteArraySet以何種方式保證元素不重複?

(16)如何比較兩個Set中的元素是否完全一致?

(17)ConcurrentSkipListSet的底層是ConcurrentSkipListMap嗎?

(18)ConcurrentSkipListSet是有序的嗎?怎麼個有序法?

關於Set的問題大概就這麼多,你都能回答上來嗎?

點選下面連結可以直接到相應的章節檢視:

死磕 java集合之HashSet原始碼分析

死磕 java集合之LinkedHashSet原始碼分析

死磕 java集合之TreeSet原始碼分析

死磕 java集合之CopyOnWriteArraySet原始碼分析

死磕 java集合之ConcurrentSkipListSet原始碼分析

Queue

Queue是一種叫做佇列的資料結構,佇列是遵循著一定原則的入隊出隊操作的集合,一般來說,入隊是在佇列尾新增元素,出隊是在佇列頭刪除元素,但是,也不一定,比如優先順序佇列的原則就稍微有些不同。

Queue

java中提供的Queue的實現主要有PriorityQueue、ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue、LinkedTransferQueue、DelayQueue、ConcurrentLinkedQueue。

關於Queue的問題主要有:

(1)什麼是堆?什麼是堆化?

(2)什麼是優先順序佇列?

(3)PriorityQueue是怎麼實現的?

(4)PriorityQueue是有序的嗎?

(5)PriorityQueue入隊、出隊的時間複雜度各是多少?

(6)PriorityQueue是否需要擴容?擴容規則呢?

(7)ArrayBlockingQueue的實現方式?

(8)ArrayBlockingQueue是否需要擴容?

(9)ArrayBlockingQueue怎麼保證執行緒安全?

(9)ArrayBlockingQueue有什麼缺點?

(10)LinkedBlockingQueue的實現方式?

(11)LinkedBlockingQueue是有界的還是無界的佇列?

(12)LinkedBlockingQueue怎麼保證執行緒安全?

(13)LinkedBlockingQueue與ArrayBlockingQueue對比?

(14)SynchronousQueue的實現方式?

(15)SynchronousQueue真的是無緩衝的嗎?

(16)SynchronousQueue怎麼保證執行緒安全?

(17)SynchronousQueue的公平模式和非公平模式有什麼區別?

(18)SynchronousQueue在高併發情景下會有什麼問題?

(19)PriorityBlockingQueue的實現方式?

(20)PriorityBlockingQueue是否需要擴容?

(21)PriorityBlockingQueue怎麼保證執行緒安全?

(22)PriorityBlockingQueue為什麼不需要notFull條件?

(23)什麼是雙重佇列?

(24)LinkedTransferQueue是怎麼實現阻塞佇列的?

(25)LinkedTransferQueue是怎麼控制併發安全的?

(26)LinkedTransferQueue與SynchronousQueue有什麼異同?

(27)ConcurrentLinkedQueue是阻塞佇列嗎?

(28)ConcurrentLinkedQueue如何保證併發安全?

(29)ConcurrentLinkedQueue能用於執行緒池嗎?

(30)DelayQueue是阻塞佇列嗎?

(31)DelayQueue的實現方式?

(32)DelayQueue主要用於什麼場景?

關於Queue的問題大概就這麼多,你都能回答上來嗎?

點選下面連結可以直接到相應的章節檢視:

死磕 java集合之PriorityQueue原始碼分析

死磕 java集合之ArrayBlockingQueue原始碼分析

死磕 java集合之LinkedBlockingQueue原始碼分析

死磕 java集合之SynchronousQueue原始碼分析

死磕 java集合之PriorityBlockingQueue原始碼分析

死磕 java集合之LinkedTransferQueue原始碼分析

死磕 java集合之ConcurrentLinkedQueue原始碼分析

死磕 java集合之DelayQueue原始碼分析

Deque

Deque是一種特殊的佇列,它的兩端都可以進出元素,故而得名雙端佇列(Double Ended Queue)。

Deque

java中提供的Deque的實現主要有ArrayDeque、LinkedBlockingDeque、ConcurrentLinkedDeque、LinkedList。

關於Deque的問題主要有:

(1)什麼是雙端佇列?

(2)ArrayDeque是怎麼實現雙端佇列的?

(3)ArrayDeque是有界的嗎?

(4)LinkedList與ArrayDeque的對比?

(5)雙端佇列是否可以作為棧使用?

(6)LinkedBlockingDeque是怎麼實現雙端佇列的?

(7)LinkedBlockingDeque是怎麼保證併發安全的?

(8)ConcurrentLinkedDeque是怎麼實現雙端佇列的?

(9)ConcurrentLinkedDeque是怎麼保證併發安全的?

(10)LinkedList是List和Deque的集合體?

關於Deque的問題大概就這麼多,你都能回答上來嗎?

點選下面連結可以直接到相應的章節檢視(LinkedBlockingDeque和ConcurrentLinkedDeque跟相應的Queue的實現方式基本一致,所以筆者沒寫這兩個類的原始碼分析):

死磕 java集合之ArrayDeque原始碼分析

死磕 java集合之LinkedList原始碼分析

總結

其實上面的問題很多都具有共性,我覺得以下幾個問題在看每個集合類的時候都要掌握清楚:

(1)使用的資料結構?

(2)新增元素、刪除元素的基本邏輯?

(3)是否是fail-fast的?

(4)是否需要擴容?擴容規則?

(5)是否有序?是按插入順序還是自然順序還是訪問順序?

(6)是否執行緒安全?

(7)使用的鎖?

(8)優點?缺點?

(9)適用的場景?

(10)時間複雜度?

(11)空間複雜度?

(12)還有呢?

彩蛋

到這裡整個集合的內容就全部完畢了,其實看了這麼多集合的原始碼之後,筆者發現,基本上所有集合類使用的資料結構都是陣列和連結串列,包括樹和跳錶也可以看成是連結串列的一種方式。

對於併發安全的集合,還要再加上相應的鎖策略,要不就是重入鎖,要不就是CAS+自旋,偶爾也來個synchronized。

所以,掌握集合的原始碼不算什麼,資料結構和鎖才是王道。

預告:下一個專題是java併發包,也就是著名的JUC,當然這裡是除了併發集合以外的內容,也就是原子類、各種鎖、執行緒池三塊硬骨頭。


歡迎關注我的公眾號“彤哥讀原始碼”,檢視更多原始碼系列文章, 與彤哥一起暢遊原始碼的海洋。

qrcode

相關文章