選對集合,事半功倍。.NET 基礎類庫 (FCL) 提供了豐富的泛型集合,但面對 List<T>、Dictionary<TKey,TValue>、Queue<T>、HashSet<T> 等眾多選擇,如何決策?本文從數據結構原理出發,建立系統性選型框架。
集合按邏輯結構分為線性與非線性:
線性集合按存儲方式再分:
| 存儲方式 | 典型類型 | 優勢 | 劣勢 |
|---|---|---|---|
| 直接存儲 (隨機訪問) | Array, List<T>, string, struct | 索引訪問 O(1),尾部添加 O(1) | 中間插入/刪除 O(n),需移動元素 |
| 順序存儲 (鏈式) | LinkedList<T>, Queue<T>, Stack<T>, Dictionary<TKey,TValue> | 插入/刪除 O(1),動態擴縮 | 查找 O(n),無索引訪問 |
List<T>最通用的動態陣列。若大小固定且無裝箱拆箱需求,優先用 T[] 陣列。
Queue<T>適用:任務調度、消息隊列、生產者-消費者模式。Enqueue/Dequeue 均 O(1)。
var cmdQueue = new Queue<Command>();
// 生產者
cmdQueue.Enqueue(new Command(...));
// 消費者線程
while (cmdQueue.TryDequeue(out var cmd)) cmd.Execute();
Stack<T>適用:撤銷操作、語法解析、深度優先搜索。Push/Pop/Peek 均 O(1)。
Dictionary<TKey,TValue>基於哈希表,查找/插入/刪除平均 O(1)。鍵需正確實現 GetHashCode/Equals。
LinkedList<T>雙向鏈表,提供 AddBefore/AddAfter/AddFirst/AddLast。無 Add 方法,需持有節點引用操作。
HashSet<T>無序、不重複。提供 UnionWith/IntersectWith/ExceptWith/SymmetricExceptWith 等集合代數運算。
SortedList<TKey,TValue>:鍵有序,內存緊湊,插入較慢SortedDictionary<TKey,TValue>:紅黑樹,插入/刪除 O(log n)SortedSet<T>:有序去重集合命名空間 System.Collections.Concurrent:
ConcurrentDictionary<TKey,TValue>ConcurrentQueue<T> / ConcurrentStack<T>ConcurrentBag<T> (無序、可重複)內部用無鎖或細粒度鎖實現線程安全,避免手動 lock 開銷。
| 操作 | List<T> | LinkedList<T> | Dictionary<TKey,TValue> | HashSet<T> |
|---|---|---|---|---|
| 索引訪問 | O(1) ✓ | O(n) | N/A | N/A |
| 尾部添加 | O(1) ✓ | O(1) ✓ | O(1) ✓ | O(1) ✓ |
| 中間插入 | O(n) | O(1)* ✓ | N/A | N/A |
| 查找 | O(n) | O(n) | O(1) ✓ | O(1) ✓ |
| 去重 | 手動 | 手動 | 鍵天然去重 | 天然 ✓ |
* 需持有目標節點引用
ArrayList, Hashtable):裝箱拆箱性能損耗大,無類型安全InvalidOperationException,改用 for 逆序或 RemoveAllnew List<T>(expectedCount) 減少擴容拷貝沒有萬能集合,只有最適合場景的集合。理解底層數據結構的時間/空間複雜度,結合業務訪問模式(讀多寫少?頻繁插入刪除?需去重?需有序?多線程?),才能做出最優選型。將本文決策樹收藏,下次選型不再猶豫。