Hashtable 實作 IDictionary,以 **雜湊演算法** 將 Key 映射為內部索引,提供 **O(1) 平均查找/插入/刪除** 能力,是處理「依鍵快速取值」場景的首選集合(.NET 2.0+ 建議改用泛型 Dictionary<TKey, TValue>)。
key.GetHashCode() → 桶索引 → 解決碰撞(鏈結串列)SortedList 或 SortedDictionarySyncRoot 提供同步包裝,非原生安全| 成員 | 說明 | 範例 |
|---|---|---|
Count | 元素數 | ht.Count |
Keys / Values | 鍵/值集合(ICollection) | foreach(var k in ht.Keys) |
Item[key] | 存取器(取/設),Key 不存在取值回傳 null,設值自動新增/覆蓋 | ht["id"] = 100 |
Add(key, value) | 新增,Key 重複拋出例外 | ht.Add(1, "one") |
Remove(key) / Clear() | 移除單筆/全部 | ht.Remove(1) |
ContainsKey / ContainsValue | 檢查存在性 | ht.ContainsKey("id") |
GetEnumerator() | 回傳 DictionaryEntry 迭代器 | foreach(DictionaryEntry de in ht) |
using System;
using System.Collections;
class StudentManager
{
private readonly Hashtable _students = new Hashtable(); // Key: 學號(string), Value: 學生姓名
public void Run()
{
while (true)
{
Console.WriteLine(@"
歡迎進入 0122 班學員登記系統
========================================
請選擇操作:A-新增 B-查詢 C-刪除 D-修改 E-離開");
var key = Console.ReadKey(true).KeyChar;
Console.WriteLine();
switch (char.ToUpper(key))
{
case 'A': Add(); break;
case 'B': Query(); break;
case 'C': Delete(); break;
case 'D': Update(); break;
case 'E': return;
default: Console.WriteLine("無效選項"); break;
}
}
}
private void Add()
{
Console.Write("學號:"); string id = Console.ReadLine();
if (_students.ContainsKey(id)) { Console.WriteLine("學號已存在"); return; }
Console.Write("姓名:"); string name = Console.ReadLine();
_students.Add(id, name);
Console.WriteLine("新增成功");
}
private void Query()
{
Console.Write("查詢學號:"); string id = Console.ReadLine();
if (_students.ContainsKey(id))
Console.WriteLine($"姓名:{_students[id]}");
else
Console.WriteLine("查無此學號");
}
private void Delete()
{
Console.Write("刪除學號:"); string id = Console.ReadLine();
if (_students.ContainsKey(id)) { _students.Remove(id); Console.WriteLine("刪除成功"); }
else Console.WriteLine("查無此學號");
}
private void Update()
{
Console.Write("修改學號:"); string id = Console.ReadLine();
if (!_students.ContainsKey(id)) { Console.WriteLine("查無此學號"); return; }
Console.Write("新姓名:"); string name = Console.ReadLine();
_students[id] = name; // 索引器自動覆蓋
Console.WriteLine("修改成功");
}
}
// 程式進入點
class Program
{
static void Main() => new StudentManager().Run();
}
歡迎進入 0122 班學員登記系統 ======================================== 請選擇操作:A-新增 B-查詢 C-刪除 D-修改 E-離開 A 學號:1 姓名:唐老鴨 新增成功 請選擇操作:A-新增 B-查詢 C-刪除 D-修改 E-離開 B 查詢學號:1 姓名:唐老鴨
| 場景 | 建議 | 理由 |
|---|---|---|
| 已知 Key 型別(如 string/int) | Dictionary<TKey, TValue> | 避免裝箱/拆箱,強型別,效能 +30%~50% |
| 需保持插入順序 | OrderedDictionary 或 List<KeyValuePair> | Hashtable 無序 |
| 需依 Key 排序 | SortedDictionary<TKey, TValue> (紅黑樹 O(log n)) | Hashtable 不支援排序 |
| 多執行緒高併發讀寫 | ConcurrentDictionary<TKey, TValue> | 無鎖/細粒度鎖,吞吐量高 |
| Key 為實值型別(int、struct) | 必須用泛型 Dictionary | Hashtable 會裝箱 Key,產生大量 GC 壓力 |
ht[1] (int) 與 ht["1"] (string) 是不同鍵。ContainsValue(null) 會掃描全表,效能差。InvalidOperationException,需先 ToList() 或收集待刪 Key 再刪。GetHashCode() 與 Equals(),且不可變欄位參與運算。下一篇將介紹 SortedList:結合陣列與雜湊表優點,支援二元搜尋與鍵值排序。