集合是 Java 開發最高頻 API。本文系統梳理 Collection 體系(List/Set)核心實現類的底層資料結構、效能特徵、適用場景與原始碼關鍵點,並附贈「隊列/堆疊模擬」、「自定義物件存入 HashSet/TreeSet 必讀」實戰指南。
Collection (介面)
├── List (有序、可重複、有索引)
│ ├── ArrayList (動態陣列) → 查詢快、增刪慢、非執行緒安全
│ ├── LinkedList (雙向鏈表) → 增刪快、查詢慢、可模擬隊列/堆疊
│ └── Vector (舊版動態陣列,同步) → 已被 ArrayList 取代,僅維護相容
└── Set (無序、不可重複)
├── HashSet (雜湊表) → 存取無序、O(1) 查找、非安全
├── LinkedHashSet (鏈表+雜湊表) → 維護插入順序/存取順序
└── TreeSet (紅黑樹) → 自然排序/定製排序、O(log N)
Object[] elementData,擴容 1.5 倍。O(1),尾部新增均攤 O(1),中間插入/刪除 O(N)(需陣列複製)。null 元素。prev/next/item。O(1):addFirst/Last、removeFirst/Last、getFirst/Last。ListIterator 雙向遍歷與增刪改查。addLast + removeFirst)與堆疊(addLast + removeLast)。synchronized,效能差,僅為相容舊代碼保留。Enumeration 已被 Iterator 取代。HashMap<E, Object>,PRESENT 為固定 value。hashCode() 與 equals(),否則無法保證唯一性(預設比較記憶體位址)。LinkedHashSet 額外維護雙向鏈表,迭代順序 = 插入順序(或存取順序)。public class Person {
private String name; private int age;
// getter/setter/toString 省略
@Override public int hashCode() {
return Objects.hash(name, age);
}
@Override public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person p = (Person) o;
return age == p.age && Objects.equals(name, p.name);
}
}
未覆寫時:同名同年齡的不同實例視為不同元素 → 重複存入。覆寫後:內容相同視為同一元素 → 去重生效。
Comparable 或提供 Comparator。compareTo == 0)捨棄。public class Person implements Comparable<Person> {
// ...
@Override public int compareTo(Person o) {
int ageDiff = this.age - o.age;
return ageDiff != 0 ? ageDiff : this.name.compareTo(o.name);
}
}
若未實作 Comparable 直接存入 TreeSet,拋 ClassCastException。
| 場景 | 推薦實現 | 理由 |
|---|---|---|
| 高頻隨機存取、尾部新增 | ArrayList | 陣列連續記憶體、CPU 快取友好 |
| 高頻頭/尾增刪、模擬隊列/堆疊 | LinkedList | 指標操作 O(1)、無擴容複製 |
| 去重、高頻含有性檢查 | HashSet | 雜湊 O(1) 查找 |
| 去重 + 保持插入順序 | LinkedHashSet | 雜湊 + 鏈表雙重結構 |
| 去重 + 自動排序 | TreeSet | 紅黑樹 O(log N) 有序 |
hashCode/equals。Comparable 且無 Comparator。list.remove() 拋 ConcurrentModificationException,需用 Iterator.remove() 或 CopyOnWriteArrayList。Collections.synchronizedList 或 CopyOnWriteArrayList。掌握底層結構,才能在海量數據、高併發場景下做出正確集合選型,避免效能陷阱。