前言
Java 集合框架是 JDK 中使用頻率最高的 API,java.util.* 包下 100+ 類/接口構成嚴謹的繼承體系。本文基於 JDK 17 源碼,從頂層接口設計、核心實現類結構、數據結構底層原理、選型決策矩陣四個維度,構建完整認知全景圖。
一、頂層接口架構:雙棲體系
┌─────────────────────┐
│ java.lang.Iterable │ ← 根接口,for-each 依賴
└──────────┬──────────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Collection │ │ Map │ │ Iterator │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌─────────┼─────────┐ │ │
▼ ▼ ▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐ ┌───────────┐
│ List │ │ Set │ │ Queue │ │ListIterator│
└───┬───┘ └───┬───┘ └───┬───┘ └───────────┘
│ │ │
▼ ▼ ▼
ArrayList HashSet PriorityQueue
LinkedList TreeSet ArrayDeque
Vector LinkedHashSet
Stack CopyOnWriteArraySet
核心接口職責
| 接口 | 核心契約 | 關鍵方法 | 實現類代表 |
| Iterable | 可迭代 | iterator()、forEach()、spliterator() | 所有 Collection |
| Collection | 單一元素容器 | add/remove/contains/size/isEmpty/toArray | List/Set/Queue |
| List | 有序、可重複、索引訪問 | get/set/add(index)/remove(index)/subList | ArrayList/LinkedList |
| Set | 無序、唯一 | 繼承 Collection,依賴 equals/hashCode | HashSet/TreeSet/LinkedHashSet |
| Queue | FIFO/優先級隊列 | offer/poll/peek/add/remove/element | ArrayDeque/PriorityQueue |
| Deque | 雙端隊列 | addFirst/Last、push/pop、descendingIterator | ArrayDeque/LinkedList |
| Map | 鍵值映射、Key 唯一 | put/get/remove/containsKey/keySet/values/entrySet | HashMap/TreeMap/ConcurrentHashMap |
| Iterator | 單向遍歷 | hasNext/next/remove/forEachRemaining | 所有 Collection |
| ListIterator | 雙向遍歷、可修改 | hasPrevious/previous/add/set/nextIndex | List 實現類 |
二、抽象類骨幹:模板方法模式
JDK 提供四大抽象類,實現接口中通用邏輯,子類只需覆蓋核心方法:
| 抽象類 | 實現接口 | 核心模板方法 | 留給子類的抽象方法 |
| AbstractCollection | Collection | toString、toArray、contains、removeAll、retainAll | iterator()、size() |
| AbstractList | List | get/set/add/remove(index)、indexOf、lastIndexOf、listIterator、subList | get(index)、size()、set(index, e)、add(index, e)、remove(index) |
| AbstractSet | Set | equals、hashCode、removeAll(優化) | 繼承 AbstractCollection |
| AbstractQueue | Queue | add、remove、element(委託 offer/poll/peek) | offer、poll、peek、size |
設計精妙:AbstractList.add(E e) 默認調用 add(size(), e),remove(Object o) 默認迭代器查找再調用 remove(index),子類只需實現隨機訪問核心邏輯。
三、核心實現類深度解析
3.1 List 族系
| 類 | 底層結構 | 特點 | 擴容/縮容 | 線程安全 | 適用場景 |
| ArrayList | Object[] 數組 | 隨機訪問 O(1),尾部增刪 O(1),中間增刪 O(n) | 1.5倍擴容,無自動縮容 | 否 | 默認首選,讀多寫少 |
| LinkedList | 雙向鏈表 | 頭尾增刪 O(1),索引訪問 O(n),實現 Deque | 無容量限制,按需分配節點 | 否 | 頻繁頭尾操作、棧/隊列 |
| Vector | Object[] 數組 | 方法級 synchronized,2倍擴容 | 2倍擴容 | 是(粗粒度) | 已過時,用 Collections.synchronizedList 或 CopyOnWriteArrayList |
| Stack | 繼承 Vector | LIFO,push/pop/peek | 同 Vector | 是 | 已過時,用 ArrayDeque |
| CopyOnWriteArrayList | 數組 + 寫時復制 | 讀無鎖,寫復制新數組,迭代器弱一致 | 每次寫全量復制 | 是(細粒度) | 讀多寫極少、遍歷併發安全 |
3.2 Set 族系
| 類 | 底層結構 | 有序性 | 線程安全 | 性能特徵 |
| HashSet | HashMap (value=PRESENT) | 無序 | 否 | O(1) 增刪查,依賴 hashCode/equals |
| LinkedHashSet | LinkedHashMap | 插入序 | 否 | 雙向鏈表維護順序,迭代有序 |
| TreeSet | TreeMap (紅黑樹) | 自然序/Comparator | 否 | O(log n),範圍查詢、有序遍歷 |
| CopyOnWriteArraySet | CopyOnWriteArrayList | 插入序 | 是 | 讀無鎖,寫全量復制 |
| ConcurrentSkipListSet | 跳表 | 自然序 | 是 (無鎖) | O(log n) 期望,高併發有序集合 |
3.3 Map 族系
| 類 | 底層結構 | 有序性 | Null Key/Value | 線程安全 | JDK8+ 優化 |
| HashMap | 數組 + 鏈表 + 紅黑樹 | 無序 | 允許 1 null key,多 null value | 否 | 鏈表≥8 樹化,≥6 退化 |
| LinkedHashMap | HashMap + 雙向鏈表 | 插入序/訪問序 | 同 HashMap | 否 | accessOrder=true 實現 LRU |
| TreeMap | 紅黑樹 | Key 自然序/Comparator | 不允許 null key | 否 | NavigableMap 範圍操作 |
| Hashtable | 數組 + 鏈表 | 無序 | 不允許 null | 是 (synchronized) | 已過時 |
| ConcurrentHashMap | 數組 + 鏈表/紅黑樹 + CAS/synchronized | 無序 | 不允許 null | 是 (分段/細粒度) | JDK8 擴容協助、CounterCell |
| WeakHashMap | HashMap + WeakReference Key | 無序 | 允許 null | 否 | Key 為弱引用,GC 自動清理 |
| IdentityHashMap | 線性探測數組 | 無序 | 允許 null | 否 | 用 == 而非 equals 比較 Key |
3.4 Queue/Deque 族系
| 類 | 底層 | 特點 | 有界性 | 線程安全 |
| ArrayDeque | 循環數組 | 雙端 O(1),無容量上限,非線程安全 | 無界 | 否 |
| PriorityQueue | 堆 (數組) | 最小堆,O(log n) 入隊出隊,無序迭代 | 無界 | 否 |
| LinkedBlockingQueue | 單向鏈表 | 可選界,鎖分離,高吞吐 | 有界/無界 | 是 |
| ArrayBlockingQueue | 循環數組 | 有界,單鎖,公平可選 | 有界 | 是 |
| ConcurrentLinkedQueue | CAS 鏈表 | 無界,無鎖,弱一致迭代 | 無界 | 是 (無鎖) |
| SynchronousQueue | 直接傳遞 | 無緩衝,生產者消費者配對 | 0 | 是 |
| DelayQueue | PriorityQueue | 延遲執行,元素實現 Delayed | 無界 | 是 |
四、選型決策矩陣:一表定乾坤
| 需求 | 首選 | 備選 | 避坑 |
| 一般列表,隨機訪問 | ArrayList | Vector (舊代碼) | 頻繁頭部增刪用 LinkedList |
| 頻繁頭尾增刪,棧/隊列 | ArrayDeque | LinkedList | LinkedList 內存開銷大、緩存不友好 |
| 去重集合,無序 | HashSet | LinkedHashSet (需序) | 自定義對象必重寫 equals/hashCode |
| 去重 + 保持插入序 | LinkedHashSet | LinkedHashMap.keySet() | |
| 去重 + 排序/範圍查詢 | TreeSet | ConcurrentSkipListSet (併發) | Key 必須 Comparable |
| 鍵值映射,高性能 | HashMap | ConcurrentHashMap (併發) | Key 正確重寫 hashCode/equals |
| 鍵值映射 + LRU 緩存 | LinkedHashMap (accessOrder=true) | Caffeine/Guava Cache | 重寫 removeEldestEntry |
| 鍵值映射 + 排序/範圍 | TreeMap | ConcurrentSkipListMap (併發) | |
| 高併發隊列,生產消費 | LinkedBlockingQueue | ArrayBlockingQueue (有界) | 無界隊列警惕 OOM |
| 線程安全列表,讀多寫少 | CopyOnWriteArrayList | Collections.synchronizedList | 寫頻繁會大量復制數組 |
| 線程安全集合,高併發 | ConcurrentHashMap.keySet() | ConcurrentSkipListSet | |
五、源碼閱讀路線圖
- ArrayList:
grow() 擴容、System.arraycopy 移動、SubList 視圖模式
- HashMap:
putVal() 核心邏輯、treeifyBin() 樹化、resize() 擴容遷移
- ConcurrentHashMap:
Node[] 數組、CAS 初始化、synchronized 鎖節點、transfer() 並發擴容
- ArrayDeque:
head/tail 指針環繞、doubleCapacity() 擴容
- LinkedHashMap:
LinkedNode 雙向鏈表、afterNodeAccess() 訪問序調整
- TreeMap:
rotateLeft/Right 紅黑樹旋轉、fixAfterInsertion 修復
六、總結
- 雙棲體系:Collection(單值)+ Map(鍵值),Iterable 統一迭代入口
- 抽象類模板:AbstractCollection/List/Set/Queue 封裝通用邏輯,降低實現門檻
- 數據結構決定性能:數組(隨機訪問) vs 鏈表(增刪) vs 紅黑樹(有序) vs 哈希表(O(1)) vs 跳表(併發有序)
- 線程安全靠組合:同步包裝器、CopyOnWrite、Concurrent* 系列、無鎖隊列
- 選型看場景:讀寫比、有序性、併發度、內存敏感度、功能豐富度
集合框架不是死記硬背 API,而是數據結構、併發控制、內存模型、泛型設計的綜合體現。掌握底層原理,選型才有依據,調優才有方向。