JDK 提供豐富的集合實現,合格開發者必須能根據功能場景與性能需求選用最合適的集合。本文系統梳理 Collection 與 Map 兩大根接口衍生出的主流實現類,剖析底層數據結構、線程安全特性、適用場景與核心參數。
Collection (根接口) ├── List (有序、可重複) → ArrayList, LinkedList, Vector, CopyOnWriteArrayList ├── Set (無序、不可重複) → HashSet, LinkedHashSet, TreeSet, ConcurrentSkipListSet └── Queue (FIFO/優先級) → PriorityQueue, ArrayBlockingQueue, LinkedBlockingQueue, ConcurrentLinkedQueue Map (鍵值對,Key 唯一) ├── HashMap, Hashtable, ConcurrentHashMap ├── LinkedHashMap (插入序/訪問序) ├── TreeMap (紅黑樹有序) └── ConcurrentSkipListMap (跳表有序+線程安全)
| 實現 | 底層結構 | 線程安全 | 隨機訪問 | 插入刪除 | 擴容機制 | 適用場景 |
|---|---|---|---|---|---|---|
| ArrayList | 動態數組 | ❌ | O(1) ✅ | O(n) 須搬移 | 1.5倍 | 讀多寫少、頻繁隨機訪問 |
| LinkedList | 雙向鏈表 | ❌ | O(n) ❌ | O(1) 僅調整指針 | 無 | 寫多讀少、頻繁頭尾增刪、實現 Queue/Deque |
| Vector | 動態數組 | ✅ 方法級 synchronized | O(1) | O(n) | 2倍(可配置) | 遺留代碼兼容,新代碼不推薦 |
| CopyOnWriteArrayList | 數組+寫時復制 | ✅ 寫鎖+volatile | O(1) | O(n) 復制整個數組 | 無 | 讀多寫極少、遍歷併發安全、最終一致性可接受 |
遍歷陷阱:LinkedList 絕對不要用
get(i)遍歷(O(n²)),必須用Iterator或增強 for 循環(O(n))。ArrayList 則隨意。
| 實現 | 底層結構 | 線程安全 | 有序性 | Null Key/Value | 核心機制 | 適用場景 |
|---|---|---|---|---|---|---|
| HashMap | 數組+鏈表/紅黑樹(JDK8) | ❌ | 無序 | 允許 1 null key, 多 null value | 拉鏈法解決哈希衝突,負載因子 0.75,樹化閾值 8 | 通用高性能鍵值存取 |
| Hashtable | 數組+鏈表 | ✅ 全表鎖 | 無序 | 不允許 null | 同步方法鎖住整個表 | 遺留代碼,新代碼用 ConcurrentHashMap |
| ConcurrentHashMap | JDK7: Segment分段鎖 JDK8: CAS+synchronized+Node | ✅ 細粒度鎖 | 無序 | 不允許 null | JDK8 鎖頭節點,擴容並發協助,value volatile 保證可見性 | 高併發讀寫、緩存、計數器 |
| LinkedHashMap | HashMap+雙向鏈表 | ❌ | 插入序/訪問序 | 允許 null | Entry 額外維護 before/after 指釖 | LRU 緩存(removeEldestEntry)、有序遍歷 |
| TreeMap | 紅黑樹 | ❌ | Key 自然序/Comparator 序 | 不允許 null key | 自平衡二叉搜索樹,O(logN) 查找/插入/刪除 | 範圍查詢、有序遍歷、極值獲取 |
| ConcurrentSkipListMap | 跳表 | ✅ 無鎖 CAS | Key 有序 | 不允許 null | 多層鏈表索引,O(logN) 期望,volatile 右指針 | 高併發有序 Map、分佈式系統序號生成 |
所有 Set 內部封裝同類型 Map:HashSet → HashMap、TreeSet → TreeMap、ConcurrentSkipListSet → ConcurrentSkipListMap。元素作為 Key 存入,Value 統一為 PRESENT = new Object()。特性與對應 Map 完全一致。
| 實現 | 類型 | 阻塞 | 有界 | 線程安全 | 底層結構 | 核心特性 |
|---|---|---|---|---|---|---|
| ConcurrentLinkedQueue | 非阻塞 | ❌ | 無界 | ✅ CAS | 單向鏈表 | 高吞吐入隊/出隊,弱一致性迭代器 |
| LinkedBlockingQueue | 阻塞 | ✅ | 可選(默認無界) | ✅ 雙鎖 | 單向鏈表 | take/put 阻塞,生產消費分離鎖,吞吐高 |
| ArrayBlockingQueue | 阻塞 | ✅ | ✅ 必須指定 | ✅ 單鎖 | 環形數組 | 固定容量,公平鎖可選,生產消費共用鎖 |
| SynchronousQueue | 阻塞 | ✅ | 0 (不存儲) | ✅ CAS | 直接傳遞 | 生產者等消費者,消費者等生產者,傳遞性場景 |
| PriorityQueue | 非阻塞 | ❌ | 無界 | ❌ | 最小堆 | 按優先級/Comparator 排序,非 FIFO |
| PriorityBlockingQueue | 阻塞 | ✅ | 無界 | ✅ 單鎖 | 最小堆 | 優先級+阻塞,線程安全 |
| LinkedBlockingDeque | 阻塞雙端 | ✅ | 可選 | ✅ 雙鎖 | 雙向鏈表 | 雙端入隊/出隊,可作棧/隊列 |
選型口訣:
高併發非阻塞 →ConcurrentLinkedQueue
生產消費模型 →LinkedBlockingQueue(無界) /ArrayBlockingQueue(有界)
直接傳遞任務 →SynchronousQueue(線程池newCachedThreadPool默認)
優先級處理 →PriorityBlockingQueue
雙端操作/棧 →LinkedBlockingDeque/ArrayDeque(非線程安全)
ConcurrentHashMapTreeMap / ConcurrentSkipListMapLinkedHashMapHashMapArrayListLinkedListCopyOnWriteArrayListadd/offer 差異:有界隊列滿時 add 拋異常,offer 返回 false;put 阻塞等待ConcurrentModificationException,但可能讀到過期數據