2024-11-01 022_各種泛型集合類別

2024-11-01 022_各種泛型集合類別

當然,C# 中的泛型集合類別(Generic Collection Classes)非常豐富,不僅僅只有 List<T>。這些泛型集合提供了不同的資料結構和功能,適用於各種不同的編程需求。以下是一些常用的泛型集合類別,除了 List<T> 之外,還包括 Dictionary<TKey, TValue>HashSet<T>Queue<T>Stack<T>LinkedList<T> 等等。我們將一步步介紹這些集合的特性及其適用情境。


目錄

  1. Dictionary<TKey, TValue>
  2. HashSet<T>
  3. Queue<T>
  4. Stack<T>
  5. LinkedList<T>
  6. SortedList<TKey, TValue>SortedDictionary<TKey, TValue>
  7. SortedSet<T>
  8. ObservableCollection<T>
  9. Concurrent Collections(如 ConcurrentDictionary<TKey, TValue>
  10. 小結

1. Dictionary<TKey, TValue>

概述:
Dictionary<TKey, TValue> 是一種鍵值對(Key-Value Pair)的集合,允許根據鍵快速查找值。每個鍵在字典中是唯一的。

用途:
適用於需要快速查找、添加和移除元素的情境,特別是當你需要根據特定鍵來存取資料時。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using System.Collections.Generic;

class Program
{
static void Main(string[] args)
{
// 創建一個 Dictionary<string, int>
Dictionary<string, int> ages = new Dictionary<string, int>();

// 添加元素
ages.Add("Alice", 30);
ages.Add("Bob", 25);
ages.Add("Charlie", 35);

// 訪問元素
int aliceAge = ages["Alice"];
Console.WriteLine($"Alice 的年齡是 {aliceAge}"); // 輸出: Alice 的年齡是 30

// 遍歷字典
foreach (var kvp in ages)
{
Console.WriteLine($"{kvp.Key} 的年齡是 {kvp.Value}");
}
}
}

輸出:

1
2
3
4
Alice 的年齡是 30
Alice 的年齡是 30
Bob 的年齡是 25
Charlie 的年齡是 35

2. HashSet<T>

概述:
HashSet<T> 是一種不允許重複元素的集合,主要用於儲存唯一的元素,並提供高效的查找、添加和移除操作。

用途:
適用於需要確保元素唯一性或執行集合運算(如聯集、交集、差集)的情境。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System;
using System.Collections.Generic;

class Program
{
static void Main(string[] args)
{
// 創建一個 HashSet<int>
HashSet<int> numbers = new HashSet<int>();

// 添加元素
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
bool added = numbers.Add(2); // 嘗試添加重複元素

Console.WriteLine($"是否成功添加 2: {added}"); // 輸出: 是否成功添加 2: False

// 遍歷 HashSet
foreach (int number in numbers)
{
Console.WriteLine(number);
}
}
}

輸出:

1
2
3
4
是否成功添加 2: False
1
2
3

3. Queue<T>

概述:
Queue<T> 是一種先進先出(FIFO, First-In-First-Out)的集合,適用於需要按照元素加入順序處理的情境。

用途:
常用於任務排程、廣度優先搜尋(BFS)等需要按順序處理元素的情境。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Collections.Generic;

class Program
{
static void Main(string[] args)
{
// 創建一個 Queue<string>
Queue<string> tasks = new Queue<string>();

// 添加元素
tasks.Enqueue("任務1");
tasks.Enqueue("任務2");
tasks.Enqueue("任務3");

// 處理元素
while (tasks.Count > 0)
{
string currentTask = tasks.Dequeue();
Console.WriteLine($"處理 {currentTask}");
}
}
}

輸出:

1
2
3
處理 任務1
處理 任務2
處理 任務3

4. Stack<T>

概述:
Stack<T> 是一種後進先出(LIFO, Last-In-First-Out)的集合,適用於需要反向處理元素的情境。

用途:
常用於實現遞迴、處理撤銷操作(Undo)、解析表達式等需要反向處理的情境。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Collections.Generic;

class Program
{
static void Main(string[] args)
{
// 創建一個 Stack<int>
Stack<int> numbers = new Stack<int>();

// 添加元素
numbers.Push(1);
numbers.Push(2);
numbers.Push(3);

// 處理元素
while (numbers.Count > 0)
{
int currentNumber = numbers.Pop();
Console.WriteLine($"彈出 {currentNumber}");
}
}
}

輸出:

1
2
3
彈出 3
彈出 2
彈出 1

5. LinkedList<T>

概述:
LinkedList<T> 是一種雙向鏈結串列,允許在任意位置高效地添加和移除元素。

用途:
適用於需要頻繁在中間插入或刪除元素的情境,尤其是在不需要隨機存取的情況下。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System;
using System.Collections.Generic;

class Program
{
static void Main(string[] args)
{
// 創建一個 LinkedList<string>
LinkedList<string> cities = new LinkedList<string>();

// 添加元素
cities.AddLast("New York");
cities.AddLast("Los Angeles");
cities.AddFirst("Chicago");

// 插入元素
LinkedListNode<string> node = cities.Find("New York");
if (node != null)
{
cities.AddBefore(node, "Houston");
}

// 遍歷 LinkedList
foreach (string city in cities)
{
Console.WriteLine(city);
}
}
}

輸出:

1
2
3
4
Chicago
Houston
New York
Los Angeles

6. SortedList<TKey, TValue>SortedDictionary<TKey, TValue>

概述:

  • **SortedList<TKey, TValue>**:基於鍵的排序,並且使用陣列實現,適合讀取操作多於寫入操作的情境。
  • **SortedDictionary<TKey, TValue>**:基於樹結構實現,適合頻繁添加和刪除元素的情境。

用途:
當需要根據鍵自動排序並快速查找元素時使用。

範例:SortedDictionary<TKey, TValue>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Collections.Generic;

class Program
{
static void Main(string[] args)
{
// 創建一個 SortedDictionary<int, string>
SortedDictionary<int, string> sortedDict = new SortedDictionary<int, string>();

// 添加元素
sortedDict.Add(3, "三");
sortedDict.Add(1, "一");
sortedDict.Add(2, "二");

// 遍歷 SortedDictionary(按鍵排序)
foreach (var kvp in sortedDict)
{
Console.WriteLine($"鍵: {kvp.Key}, 值: {kvp.Value}");
}
}
}

輸出:

1
2
3
鍵: 1, 值: 一
鍵: 2, 值: 二
鍵: 3, 值: 三

7. SortedSet<T>

概述:
SortedSet<T> 是一種自動排序且不允許重複元素的集合,基於紅黑樹實現。

用途:
適用於需要儲存唯一元素並保持排序的情境,並且支持高效的集合運算(如聯集、交集)。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System;
using System.Collections.Generic;

class Program
{
static void Main(string[] args)
{
// 創建一個 SortedSet<int>
SortedSet<int> numbers = new SortedSet<int> { 5, 3, 8, 1, 2 };

// 添加元素
numbers.Add(4);

// 嘗試添加重複元素
bool added = numbers.Add(3); // 不會添加成功

Console.WriteLine($"是否成功添加 3: {added}"); // 輸出: 是否成功添加 3: False

// 遍歷 SortedSet(自動排序)
foreach (int number in numbers)
{
Console.WriteLine(number);
}
}
}

輸出:

1
2
3
4
5
6
7
是否成功添加 3: False
1
2
3
4
5
8

8. ObservableCollection<T>

概述:
ObservableCollection<T> 是一種特殊的集合,當集合中的元素發生變化(添加、移除)時,會發出通知。常用於資料綁定(Data Binding)場景,如 WPF 或 Xamarin 應用程式。

用途:
適用於需要監聽集合變化並自動更新 UI 的情境。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

class Program
{
static void Main(string[] args)
{
// 創建一個 ObservableCollection<string>
ObservableCollection<string> fruits = new ObservableCollection<string>();

// 訂閱 CollectionChanged 事件
fruits.CollectionChanged += Fruits_CollectionChanged;

// 添加元素
fruits.Add("Apple");
fruits.Add("Banana");
fruits.Remove("Apple");
}

private static void Fruits_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (string newItem in e.NewItems)
{
Console.WriteLine($"添加: {newItem}");
}
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (string oldItem in e.OldItems)
{
Console.WriteLine($"移除: {oldItem}");
}
}
}
}

輸出:

1
2
3
添加: Apple
添加: Banana
移除: Apple

9. Concurrent Collections(如 ConcurrentDictionary<TKey, TValue>

概述:
Concurrent Collections 是一組為多線程環境設計的集合類別,提供線程安全的操作。常見的有 ConcurrentDictionary<TKey, TValue>ConcurrentBag<T>ConcurrentQueue<T> 等。

用途:
適用於需要在多線程環境下安全地存取和修改集合的情境,避免競爭條件(Race Conditions)。

範例:ConcurrentDictionary<TKey, TValue>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

class Program
{
static void Main(string[] args)
{
// 創建一個 ConcurrentDictionary<string, int>
ConcurrentDictionary<string, int> concurrentDict = new ConcurrentDictionary<string, int>();

// 使用多線程添加元素
Parallel.For(0, 1000, i =>
{
concurrentDict.TryAdd($"Key{i}", i);
});

Console.WriteLine($"字典中有 {concurrentDict.Count} 個元素");
}
}

輸出:

1
字典中有 1000 個元素

10. 小結

C# 提供了豐富的泛型集合類別,每種類型都有其特定的用途和優勢。以下是各主要泛型集合類別的快速比較:

集合類別 特性 適用情境
List<T> 動態大小、快速隨機存取 一般用途,需要頻繁添加和訪問元素
Dictionary<TKey, TValue> 鍵值對、快速查找 根據鍵存取值,需要唯一鍵
HashSet<T> 唯一元素、快速查找、集合運算 需要確保元素唯一性,執行聯集、交集等集合運算
Queue<T> FIFO(先進先出) 任務排程、廣度優先搜尋等按順序處理元素的情境
Stack<T> LIFO(後進先出) 實現遞迴、處理撤銷操作等需要反向處理的情境
LinkedList<T> 雙向鏈結、快速插入和移除元素 頻繁在中間插入或刪除元素,不需要隨機存取
SortedList<TKey, TValue> 鍵排序、基於陣列實現 需要根據鍵排序且讀取操作多於寫入操作的情境
SortedDictionary<TKey, TValue> 鍵排序、基於樹結構實現 需要根據鍵排序且頻繁添加和刪除元素的情境
SortedSet<T> 自動排序、唯一元素、集合運算 需要儲存唯一且自動排序的元素,支持集合運算
ObservableCollection<T> 集合變化通知 資料綁定場景,如 WPF、Xamarin,需監聽集合變化
ConcurrentDictionary<TKey, TValue> 線程安全、適用於多線程環境 多線程環境下需要安全存取和修改字典的情境

選擇適合的泛型集合類別能夠顯著提高程式的效率和可讀性。根據你的具體需求選擇合適的集合類型,能讓你的程式碼更加優雅和高效。

如果你對某個特定的泛型集合類別有更多的疑問或需要更詳細的範例,請隨時告訴我!