本文聚焦 C#/.NET 體系下的三大經典集合:**HashSet<T>**、**Hashtable**、**TreeSet**(實為 SortedSet<T>),從底層數據結構、核心 API、性能特徵、適用場景四個維度深度對比,助你精準選型。
new HashSet<T>() // 默認比較器 new HashSet<T>(IEnumerable<T> collection) // 從集合初始化 new HashSet<T>(IEqualityComparer<T> comparer) // 自定義相等比較 new HashSet<T>(IEnumerable<T>, IEqualityComparer<T>)
| 方法 | 數學意義 | 說明 | |
|---|---|---|---|
UnionWith(other) | 並集 ∪ | 當前集合添加 other 中所有元素 | |
IntersectWith(other) | 交集 ∩ | 僅保留當前與 other 共有元素 | |
ExceptWith(other) | 差集 − | 移除 other 中存在的元素 | |
SymmetricExceptWith(other) | 對稱差集 △ | 保留僅在其中一個集合出現的元素 | |
IsSubsetOf(other) | 子集 ⊆ | 當前元素全在 other 中 | |
IsProperSubsetOf(other) | 真子集 ⊂ | 子集且不相等 | |
IsSupersetOf(other) | 超集 ⊇ | other 元素全在當前中 | |
Overlaps(other) | 相交 | 至少有一個共同元素 | |
SetEquals(other) | 相等 = | 元素完全相同 |
| 維度 | HashSet<T> | SortedSet<T> |
|---|---|---|
| 底層結構 | 哈希表 (桶+鏈表/樹) | 紅黑樹 (自平衡 BST) |
| 順序 | 無序 | 升序 (可定制 Comparer) |
| Null 支持 | 允許 1 個 null | 不允許 |
| 單操作複雜度 | O(1) 平均 | O(log n) |
| 集合運算 | 豐富 (原地修改) | 較少 (需手動實現) |
| 範圍查詢 | 不支持 | GetViewBetween 高效支持 |
| 內存佔用 | 較大 (負載因子預留) | 較小 (緊湊節點) |
Hashtable 為非泛型集合** (存 Object),**強烈建議新代碼改用 Dictionary<TKey, TValue>** 或 ConcurrentDictionary<TKey, TValue>。本節僅供維護舊代碼參考。
synchronized (鎖整個表)newCapacity = old * 2 + 1 (質數傾向)GetHashCode() 定位桶位,Equals() 解決衝突| 特性 | Hashtable | Dictionary<TKey,TValue> | ConcurrentDictionary<TKey,TValue> |
|---|---|---|---|
| 泛型 | 否 (Object) | 是 | 是 |
| 線程安全 | 是 (全表鎖) | 否 | 是 (細粒度鎖/CAS) |
| Null Key/Value | 全禁 | 允許 | Value 允許, Key 禁 |
| 性能 (單線程) | 低 (鎖開銷) | 最高 | 略低於 Dictionary |
| 性能 (多線程讀多) | 極低 | 需外部鎖 | 高 (無鎖讀) |
| 推薦場景 | 舊代碼維護 | 單線程/外部同步 | 高併發 KV 存儲 |
需要 Key-Value 映射?
├─ 是 → 高併發? → 是 → ConcurrentDictionary
│ └─ 否 → Dictionary
└─ 否 → 需要有序/範圍查詢?
├─ 是 → SortedSet / SortedDictionary
└─ 否 → 需要集合運算(並/交/差)?
├─ 是 → HashSet
└─ 是 → 只需去重/存在性判斷 → HashSet
└─ 兼容舊代碼 → Hashtable (不推薦新用)
HashSet 用 IEqualityComparer,SortedSet 用 IComparer,Dictionary 同 HashSet。掌握三者底層結構差異(哈希表 vs 紅黑樹)、線程安全模型、API 設計哲學,即可在 .NET 集合選型中游刃有餘。