首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 集合教學(二):Hashtable 雜湊表 — 鍵值對高效查找與動態擴容

     編輯:關於C#

Hashtable 實作 IDictionary,以 **雜湊演算法** 將 Key 映射為內部索引,提供 **O(1) 平均查找/插入/刪除** 能力,是處理「依鍵快速取值」場景的首選集合(.NET 2.0+ 建議改用泛型 Dictionary<TKey, TValue>)。

核心特性

  • Key-Value 鍵值對:Key 唯一、不可為 null;Value 可重複、可為 null
  • 雜湊碼分桶:key.GetHashCode() → 桶索引 → 解決碰撞(鏈結串列)
  • 動態擴容:負載因子預設 1.0,元素數/桶數 > 1.0 時自動擴容(質數桶大小)
  • 非排序:迭代順序不可預期,若需排序請用 SortedList 或 SortedDictionary
  • 執行緒安全:僅 SyncRoot 提供同步包裝,非原生安全

常用屬性與方法速查

成員說明範例
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)必須用泛型 DictionaryHashtable 會裝箱 Key,產生大量 GC 壓力

避坑提醒

  1. Key 型別一致性:ht[1] (int) 與 ht["1"] (string) 是不同鍵。
  2. Value 為 null 仍佔用槽位:ContainsValue(null) 會掃描全表,效能差。
  3. Foreach 迭代中不可修改集合:會拋 InvalidOperationException,需先 ToList() 或收集待刪 Key 再刪。
  4. 自訂類別作 Key:務必同時覆寫 GetHashCode() 與 Equals(),且不可變欄位參與運算。

下一單元預告

下一篇將介紹 SortedList:結合陣列與雜湊表優點,支援二元搜尋與鍵值排序。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved