集合體系概覽
Collection
├── List (有序、可重複)
│ ├── ArrayList (動態數組、非同步、隨機訪問快)
│ ├── LinkedList (雙向鏈表、非同步、首尾增刪快、可作棧/隊列)
│ ├── Vector (動態數組、同步、線程安全)
│ └── Stack (Vector 子類、後進先出)
└── Set (無序、不可重複)
├── HashSet (HashMap 鍵集、非同步)
└── TreeSet (紅黑樹、有序)
Map (鍵值映射、不繼承 Collection)
├── Hashtable (同步、不允許 null 鍵/值)
├── HashMap (非同步、允許一個 null 鍵、多個 null 值)
└── WeakHashMap (弱引用鍵、GC 可回收無外部引用鍵)
核心接口契約
Collection
- 兩個標準構造器:無參(空集合)、
Collection 參數(複製構造)。
- 統一遍歷方式:
Iterator it = c.iterator(); while(it.hasNext()) { Object o = it.next(); }
List
- 有序,索引訪問,允許重複元素。
- 額外提供
ListIterator:雙向遍歷、add()/set()/remove() 修改操作。
Set
- 無重複:
e1.equals(e2) == false;最多一個 null。
- 構造器約束:傳入集合不得含重複元素。
- 警惕可變對象:若元素修改導致
equals 判等,將破壞 Set 不變量。
Map
- 鍵唯一,每鍵映射單值。
- 三種視圖:
keySet()、values()、entrySet()。
主要實現類深度解析
ArrayList
- 底層
Object[],size、isEmpty、get、set 為 O(1);add 均攤 O(1)(擴容觸發 System.arraycopy)。
ensureCapacity() 預分配可大幅提升批量插入性能。
- 非同步,單線程或外部同步首選。
LinkedList
- 雙向鏈表,實現
Deque、Queue,首尾操作 O(1)。
- 索引訪問 O(n) —— 從離目標最近的一端遍歷。
- 插入/刪除僅調整指針,但需創建
Entry 節點對象(GC 壓力)。
- 非同步;同步包裝器
Collections.synchronizedList() 會帶來 2-3 倍性能損耗(每調用多一層委派)。
Vector & Stack
- Vector 方法同步,迭代器若發現併發修改拋
ConcurrentModificationException。
- Stack 繼承 Vector,提供
push/pop/peek/empty/search。
- 現代併發場景建議改用
java.util.concurrent (如 CopyOnWriteArrayList、ArrayDeque)。
Hashtable
- 同步,
put/get O(1)。initialCapacity、loadFactor (默認 0.75) 調優空間/時間。
- 鍵必正確實現
hashCode() 與 equals():equals 相等 ⇒ hashCode 必相等;僅重寫其一會導致查找失效。
HashMap
- 非同步,允許
null 鍵/值。迭代器遍歷時間與容量成正比,迭代性能敏感場景勿設過大初始容量或過小 loadFactor。
- JDK 8+ 引入紅黑樹優化高衝突桶,但基本契約不變。
WeakHashMap
- 鍵為弱引用:無外部強引用時 GC 可回收鍵及其條目,適用於緩存、監聽器映射等場景。
選型決策表
| 場景 | 推薦類 | 理由 |
| 堆疊/隊列/雙端隊列 | LinkedList | 實現 Deque/Queue,首尾 O(1) |
| 高頻隨機訪問、尾部增刪 | ArrayList | 連續內存、CPU 緩存友好、均攤 O(1) |
| 高頻中間插入/刪除 | LinkedList | 無元素移動,僅指針調整 |
| 單線程/外部同步 | ArrayList / HashMap / HashSet | 無鎖開銷,性能最優 |
| 多線程併發讀寫 | Collections.synchronizedXxx / ConcurrentHashMap / CopyOnWriteArrayList | 針對併發優化,避免包裝器性能陷阱 |
| 鍵值映射、需 null 鍵 | HashMap | 非同步、允許 null |
| 鍵值映射、線程安全 | ConcurrentHashMap | 分段鎖/無鎖讀,高併發吞吐 |
| 緩存、監聽器映射 | WeakHashMap | 鍵可被 GC 回收,防止內存洩漏 |
最佳實踐原則
- 面向接口編程:聲明用
List/Map/Set,實例化具體實現,便於後續替換。
- 鍵類正確重寫 hashCode/equals:同時重寫,保持契約一致性。
- 預估規模預分配:
new ArrayList(1000)、new HashMap(512) 減少擴容/重哈希開銷。
- 併發首選 java.util.concurrent:而非同步包裝器或 Vector/Hashtable。