集合框架頂層架構
java.util.Collection (接口)
├── List (有序、可重復)
│ ├── ArrayList (動態數組,查快增刪慢)
│ ├── LinkedList (雙向鏈表,增刪快查慢)
│ └── Vector (線程安全,已淘汰)
├── Set (無序、不可重復)
│ ├── HashSet (哈希表,O(1) 查重)
│ ├── LinkedHashSet (維護插入順序)
│ └── TreeSet (紅黑樹,天然有序)
└── Queue (隊列)
├── PriorityQueue (優先隊列)
└── ArrayDeque (雙端隊列)
java.util.Map (鍵值映射,Key 唯一)
├── HashMap (哈希表,JDK8+ 鏈表轉紅黑樹)
├── LinkedHashMap (維護插入/訪問順序)
├── TreeMap (紅黑樹,Key 有序)
├── Hashtable (線程安全,已淘汰)
└── ConcurrentHashMap (高並發線程安全)
核心接口方法速查
| 接口 | 核心方法 | 說明 |
| Collection | add, remove, contains, size, isEmpty, iterator | 單列集合基礎操作 |
| Iterator | hasNext, next, remove | 通用遍歷器,支持邊遍歷邊刪除 |
| List | get(index), set(index, e), add(index, e), subList | 索引訪問、範圍視圖 |
| Set | 繼承 Collection,無新增方法 | 靠 equals/hashCode 保證唯一 |
| Map | put, get, remove, keySet, values, entrySet | 雙列集合,Key-Value 映射 |
ArrayList vs LinkedList 選型決策樹
- 頻繁 隨機訪問 (get/index) → ArrayList (O(1))。
- 頻繁 頭尾增刪 (addFirst/removeLast) → LinkedList (O(1))。
- 中間插入刪除均較少 → ArrayList (緩存友好、內存佔用少)。
- 需實現
Queue/Deque → LinkedList (實現了雙端隊列接口)。
HashSet 去重原理與 hashCode/equals 契約
// 正確重寫規則
@Override public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person p = (Person) o;
return Objects.equals(id, p.id); // 業務主鍵判等
}
@Override public int hashCode() {
return Objects.hash(id); // 必須與 equals 使用相同字段
}
⚠️ 違反契約後果:set.contains(obj) 返回 false 但實際存在,導致重複元素無法檢測。
TreeSet / TreeMap 自定義排序
// 1. EntrySet 遍歷(推薦,單次查找)
for (Map.Entry<K, V> entry : map.entrySet()) { ... }
// 2. KeySet + get(兩次查找,較慢)
for (K key : map.keySet()) { V v = map.get(key); }
// 3. Lambda forEach (JDK 8+,代碼簡潔)
map.forEach((k, v) -> { ... });
// 4. Iterator 遍歷(需邊遍歷邊刪除時)
Iterator<Map.Entry<K, V>> it = map.entrySet().iterator();
while (it.hasNext()) { if (cond) it.remove(); }
線程安全集合選擇
| 場景 | 推薦 | 備註 |
| 高並發讀寫 | ConcurrentHashMap | 分段鎖/CAS,性能最優 |
| 僅需同步 List/Set | Collections.synchronizedList/set | 全量鎖,並發度低 |
| 複製於寫入 | CopyOnWriteArrayList/Set | 讀多寫少,遍歷無需加鎖 |
避坑清單
ArrayList 非線程安全,多線程用 CopyOnWriteArrayList 或 Collections.synchronizedList。
HashMap 多線程 put 導致死循環 (JDK 7) 或數據丟失 (JDK 8),必須用 ConcurrentHashMap。
- 遍歷時直接
list.remove() 拋 ConcurrentModificationException,改用 Iterator.remove() 或並發集合。
- 作為 Key 的對象必須 不可變 (final 字段),否則 hashCode 改變導致找不到值。