集合是動態數組,性能高、易擴展。本文梳理 Collection 體系、List/Set/Map 三大介面核心實現、選型決策、Iterator 遍歷模式及源碼級性能特徵。
Collection (interface)
├── List (有序、可重複)
│ ├── ArrayList (動態數組,擴容 1.5x)
│ ├── Vector (同步,擴容 2x,舊API)
│ └── LinkedList (雙向鏈表,實現 Queue/Deque)
├── Set (無重複)
│ ├── HashSet (HashMap 底層,無序,O(1))
│ ├── LinkedHashSet (鏈表維護插入序)
│ └── TreeSet (紅黑樹,有序,O(log n))
└── Queue
├── PriorityQueue (堆,O(log n))
└── ArrayDeque (環形數組,O(1) 首尾)
Map (interface)
├── HashMap (數組+鏈表/紅黑樹,JDK8 鏈表轉樹閾值 8)
├── LinkedHashMap (雙向鏈表維護插入/訪問序)
├── TreeMap (紅黑樹,Key 有序)
├── Hashtable (同步,舊API,Key/Value 不可 null)
└── ConcurrentHashMap (CAS+Synchronized 分段鎖/JDK8 鏈表轉樹)
| 實現 | 底層 | 隨機訪問 | 頭尾增刪 | 中間增刪 | 線程安全 | 擴容 |
|---|---|---|---|---|---|---|
| ArrayList | Object[] | O(1) ✓ | O(1) 擴容均攤 | O(n) 需搬移 | 否 | 1.5x |
| Vector | Object[] | O(1) | O(1) | O(n) | 是 (方法級 synchronized) | 2x |
| LinkedList | Node 雙向鏈表 | O(n) | O(1) ✓ | O(1) 定位後 | 否 | 無 |
口訣:常查、尾插 → ArrayList;首尾頻增刪、當隊列/棧 → LinkedList;極少用 Vector(性能差、API 老舊)。
| 實現 | 底層 | 有序性 | 查找/增刪 | Null 元素 |
|---|---|---|---|---|
| HashSet | HashMap<E,Object> | 無序 | O(1) | 允許 1 個 |
| LinkedHashSet | HashMap + 雙向鏈表 | 插入序 | O(1) | 允許 1 個 |
| TreeSet | TreeMap (紅黑樹) | 自然序/Comparator 序 | O(log n) | 不允許 |
| 實現 | 底層 | Key 有序 | Null Key | 線程安全 | JDK8 優化 |
|---|---|---|---|---|---|
| HashMap | Node[] + 鏈表/樹 | 無序 | 允許 1 個 | 否 | 鏈表長度≥8 && 數組≥64 → 紅黑樹 |
| LinkedHashMap | HashMap + 雙向鏈表 | 插入序/訪問序 | 允許 1 個 | 否 | 同上 |
| TreeMap | 紅黑樹 | 自然序/Comparator | 不允許 | 否 | — |
| Hashtable | Entry[] + 鏈表 | 無序 | 不允許 | 是 (synchronized) | — |
| ConcurrentHashMap | Node[] + 鏈表/樹 + CAS | 無序 | 不允許 | 高並發安全 | JDK8 擴容協助、鏈表轉樹 |
// 通用遍歷
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
// it.remove(); // 安全刪除當前元素
}
// for-each (語法糖,底層同 Iterator)
for (String s : list) { ... }
// Map 遍歷三種
for (Map.Entry<K,V> e : map.entrySet()) { ... } // 推薦
for (K k : map.keySet()) { V v = map.get(k); } // 兩次查找
map.forEach((k,v) -> { ... }); // Java 8 Lambda
grow() → newCapacity = old + (old >> 1),Arrays.copyOf 複製數組hash(key) → (n-1)&hash → 索引,衝突鏈表/樹化,resize() 2倍擴容並重新分佈synchronized(Node) + CAS + Node[] 細粒度鎖,size() 用 LongAdder 累加accessOrder 為 true 時 get() 會將節點移至尾部,實現 LRU 緩存List<String> list = new ArrayList<>()new ArrayList(1000) 減少擴容Iterator.remove(),不可直接 list.remove() (CME)HashMap Key 必須正確重寫 equals/hashCodeCollections.synchronizedList 或 CopyOnWriteArrayList / ConcurrentHashMap精通集合框架的底層數據結構與性能特徵,是寫出高性能 Java 代碼、通過高級面試的核心基本功。