集合框架核心結構
Java Collections Framework 以 Collection 和 Map 為雙根,提供統一操作接口:
Collection (I)
├── List (I) 有序、可重複
│ ├── ArrayList 動態數組、隨機訪問快
│ ├── LinkedList 雙向鏈表、增刪快、實現 Deque
│ ├── Vector 同步、已過時
│ └── Stack LIFO、繼承 Vector
└── Set (I) 唯一性
├── HashSet HashMap 底層、無序
├── LinkedHashSet 保持插入順序
└── TreeSet 紅黑樹、有序、O(log n)
Map (I)
├── HashMap 數組+鏈表/紅黑樹、非同步
├── LinkedHashMap 保持插入/訪問順序
├── TreeMap 紅黑樹、有序鍵
├── Hashtable 同步、已過時
├── WeakHashMap 弱鍵、GC 自動清理
└── ConcurrentHashMap 分段鎖/CAS、高併發
List 選型決策樹
| 場景 | 推薦 | 理由 |
| 頻繁隨機訪問、少量增刪 | ArrayList | 底層數組、O(1) 訪問 |
| 頻繁頭尾增刪、作為隊列/棧 | LinkedList | 鏈表結構、O(1) 首尾操作 |
| 單線程/線程封閉 | ArrayList | 無同步開銷、性能最優 |
| 多線程共享、低併發 | Vector / Collections.synchronizedList | 方法級同步 |
| 多線程共享、高併發讀多寫少 | CopyOnWriteArrayList | 寫時復制、讀無鎖 |
Fail-Fast 機制深度解析
觸發條件
迭代過程中,集合結構被修改(add/remove/clear 導致 modCount 變化),Iterator.next() 檢測到 expectedModCount != modCount 拋出 ConcurrentModificationException。
源碼級還原
// AbstractList.iterator()
public Iterator iterator() {
return new Itr(); // 內部類,捕獲 expectedModCount = modCount
}
private class Itr implements Iterator {
int cursor, lastRet = -1;
int expectedModCount = modCount; // 快照
public E next() {
checkForComodification(); // 核心檢查
// ...
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
多線程下的必現場景
List list = new ArrayList<>();
// 線程 A 遍歷
new Thread(() -> {
for (Integer i : list) { /* 讀 */ }
}).start();
// 線程 B 修改
new Thread(() -> {
list.add(999); // modCount++,線程 A 下次 next() 必拋異常
}).start();
CopyOnWriteArrayList:讀寫分離終極方案
核心原理
- 讀操作:直接訪問當前數組,無鎖、無檢查、極快
- 寫操作:
ReentrantLock 加鎖 → 復制新數組 → 修改 → volatile 切換引用
- 迭代器:構建時快照當前數組,遍歷快照,不檢查 modCount
// COWIterator 簡化版
static final class COWIterator implements ListIterator {
private final Object[] snapshot; // 構建時快照
private int cursor;
COWIterator(Object[] elements) {
this.snapshot = elements; // 無 expectedModCount!
}
public boolean hasNext() { return cursor < snapshot.length; }
public E next() { return (E) snapshot[cursor++]; }
// 無 checkForComodification()!
}
適用與不適用場景
| 適用 | 不適用 |
| 讀多寫少(緩存、監聽器列表、配置) | 寫多場景(頻繁復制數組、GC 壓力大) |
| 遍歷時允許見到舊數據(最終一致) | 需實時強一致性遍歷 |
| 集合較小(<1000 元素) | 大集合寫入(復制開銷 O(n)) |
Map 體系精華
- HashMap:JDK 8 引入紅黑樹退化鏈表、擴容優化、
putVal 核心邏輯
- ConcurrentHashMap:JDK 7 分段鎖 → JDK 8 CAS+synchronized 節點、
size() LongAdder
- TreeMap:紅黑樹、
NavigableMap 接口(floor/ceiling/higher/lower)
- WeakHashMap:Key 為弱引用、Entry 繼承 WeakReference、GC 時自動清理
Iterator vs Enumeration
| 特性 | Iterator | Enumeration |
| 方法 | hasNext/next/remove | hasMoreElements/nextElement |
| 刪除支持 | 支持 | 不支持 |
| Fail-Fast | 支持 | 不支持 |
| 性能 | 略慢(檢查開銷) | 略快 |
| 適用 | 現代代碼、需安全刪除 | 舊 API(Vector/Hashtable/Properties) |
實戰建議
- 優先
ArrayList/HashMap/HashSet,按需升級
- 多線程寫入用
ConcurrentHashMap/CopyOnWriteArrayList
- 遍歷中需刪除 →
Iterator.remove() 或 list.removeIf() (JDK 8)
- 避免在循環中調用
size() 等同步方法
- 集合作為方法參數/返回值 → 使用接口類型(
List 而非 ArrayList)