1. 程式人生 > 程式設計 >聊聊C# 中HashTable與Dictionary的區別說明

聊聊C# 中HashTable與Dictionary的區別說明

1. 雜湊表(HashTable)簡述

在.NET Framework中,Hashtable是System.Collections名稱空間提供的一個容器,用於處理和表現類似keyvalue的鍵值對,其中key通常可用來快速查詢,同時key是區分大小寫;value用於儲存對應於key的值。Hashtable中keyvalue鍵值對均為object型別,所以Hashtable可以支援任何型別的keyvalue鍵值對.

2. 什麼情況下使用雜湊表

(1)某些資料會被高頻率查詢(2)資料量大(3)查詢欄位包含字串型別(4)資料型別不唯一

3. 雜湊表的使用方法

雜湊表需要使用的namespace

using System.Collections;
using System.Collections.Generic;

雜湊表的基本操作:

//新增一個keyvalue鍵值對:
HashtableObject.Add(key,value);
//移除某個keyvalue鍵值對:
HashtableObject.Remove(key);
//移除所有元素:      
HashtableObject.Clear(); 
// 判斷是否包含特定鍵key:
HashtableObject.Contains(key);

控制檯程式例子:

using System;
using System.Collections; //file使用Hashtable時,必須引入這個名稱空間
class Program
{
 public static void Main()
 {
   Hashtable ht = new Hashtable(); //建立一個Hashtable例項
   ht.Add("北京","帝都"); //新增keyvalue鍵值對
   ht.Add("上海","魔都");
   ht.Add("廣州","省會");
   ht.Add("深圳","特區");
   string capital = (string)ht["北京"];
   Console.WriteLine(ht.Contains("上海")); //判斷雜湊表是否包含特定鍵,其返回值為true或false
   ht.Remove("深圳"); //移除一個keyvalue鍵值對
   ht.Clear(); //移除所有元素
 }
}   

雜湊表中使用多種資料型別的例子:

using System;
using System.Collections;
class Program
{
  static Hashtable GetHashtable()
  {
    Hashtable hashtable = new Hashtable();
    
    hashtable.Add("名字","小麗");
    hashtable.Add("年齡",22);
    return hashtable;
  }
  static void Main()
  {
    Hashtable hashtable = GetHashtable();
    string name = (string)hashtable["名字"];
    Console.WriteLine(name);
    int age = (int)hashtable["年齡"];
    Console.WriteLine(age);
  }
}

當獲取雜湊表中資料時,如果型別宣告的不對,會出現InvalidCastException錯誤。使用as-statements可以避免該錯誤。

using System;
using System.Collections;
using System.IO;
class Program
{
  static void Main()
  {
  Hashtable hashtable = new Hashtable();
  hashtable.Add(100,"西安");
  // 能轉換成功
  string value = hashtable[100] as string;
  if (value != null)
  {
    Console.WriteLine(value);
  }
  // 轉換失敗,獲取的值為null,但不會丟擲錯誤。
  StreamReader reader = hashtable[100] as StreamReader;
  if (reader == null)
  {
     Console.WriteLine("西安不是StreamReader型");
  }
  // 也可以直接獲取object值,再做判斷
  object value2 = hashtable[100];
  if (value2 is string)
  {
    Console.Write("這個是字串型: ");
    Console.WriteLine(value2);
  }
  }
}

4. 遍歷雜湊表

遍歷雜湊表需要用到DictionaryEntry Object,程式碼如下:

for(DictionaryEntry de in ht) //ht為一個Hashtable例項
{
  Console.WriteLine(de.Key); //de.Key對應於keyvalue鍵值對key
  Console.WriteLine(de.Value); //de.Key對應於keyvalue鍵值對value
}

遍歷鍵

foreach (int key in hashtable.Keys)
{
  Console.WriteLine(key);
}

遍歷值

foreach (string value in hashtable.Values)
{
  Console.WriteLine(value);
}

5. 對雜湊表進行排序

對雜湊表按key值重新排列的做法:

ArrayList akeys=new ArrayList(ht.Keys); 
akeys.Sort(); //按字母順序進行排序
foreach(string key in akeys)
{
  Console.WriteLine(key + ": " + ht[key]); //排序後輸出
}

6. 雜湊表的效率

System.Collections下的雜湊表(Hashtable)和System.Collections.Generic下的字典(Dictionary)都可用作lookup table,下面比較一下二者的執行效率。

Stopwatch sw = new Stopwatch();
Hashtable hashtable = new Hashtable();
Dictionary<string,int> dictionary = new Dictionary<string,int>();
int countNum = 1000000;
sw.Start();
for (int i = 0; i < countNum; i++)
{
  hashtable.Add(i.ToString(),i);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); //輸出: 744
sw.Restart();
for (int i = 0; i < countNum; i++)
{
  dictionary.Add(i.ToString(),i);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); //輸出: 489
sw.Restart();
for (int i = 0; i < countNum; i++)
{
  hashtable.ContainsKey(i.ToString());
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); //輸出: 245
sw.Restart();
for (int i = 0; i < countNum; i++)
{
  dictionary.ContainsKey(i.ToString());
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); //輸出: 192

由此可見,新增資料時Hashtable快。頻繁呼叫資料時Dictionary快。

結論:

Dictionary<K,V>是泛型的,當K或V是值型別時,其速度遠遠超過Hashtable。

補充:C# 雜湊表Hashtable與字典表Dictionary<K,V>的比較。

一、Hashtable 和 Dictionary <K,V> 型別

1):單執行緒程式中推薦使用 Dictionary,有泛型優勢,且讀取速度較快,容量利用更充分.

2):多執行緒程式中推薦使用 Hashtable,預設的 Hashtable 允許單執行緒寫入,多執行緒讀取,對 Hashtable 進一步呼叫 Synchronized()方法可以獲得完全執行緒安全的型別. 而Dictionary 非執行緒安全,必須人為使用 lock 語句進行保護,效率大減.

3):Dictionary 有按插入順序排列資料的特性 (注: 但當呼叫 Remove() 刪除過節點後順序被打亂),因此在需要體現順序的情境中使用 Dictionary 能獲得一定方便.

在使用雜湊表儲存集合元素(一種鍵/值對)時,首先要根據鍵自動計算雜湊程式碼,以確定該元素的儲存位置,再把元素的值放入相應位置所指向的儲存桶中。在查詢時,再次通過鍵所對應的雜湊程式碼到特定儲存桶中搜索,這樣將大大減少為查詢一個元素進行比較的次數。

HashTable中的key/value均為object型別,由包含集合元素的儲存桶組成。儲存桶是 HashTable中各元素的虛擬子組,與大多數集合中進行的搜尋和檢索相比,儲存桶可令搜尋和檢索更為便捷。每一儲存桶都與一個雜湊程式碼關聯,該雜湊程式碼是使用雜湊函式生成的並基於該元素的鍵。HashTable的優點就在於其索引的方式,速度非常快。如果以任意型別鍵值訪問其中元素會快於其他集合,特別是當資料量特別大的時候,效率差別尤其大。

HashTable的應用場合有:做物件快取,樹遞迴演算法的替代,和各種需提升效率的場合。

二、雜湊表Hashtabl

Hastable是雜湊表的實現,能根據關鍵字取關鍵值,這key的型別是object,value的型別也是object。

在雜湊表中新增一個key/value鍵值對:HashtableObject.Add(key,value);

在雜湊表中去除某個key/value鍵值對:HashtableObject.Remove(key);

從雜湊表中移除所有元素: HashtableObject.Clear();

判斷雜湊表是否包含特定鍵key: HashtableObject.Contains(key);

遍歷Hashtable物件的兩種方法:

由於Hashtable每個元素都是一個鍵/值對,因此元素型別既不是鍵的型別,也不是值的型別,而是DictionaryEntry型別。

Hashtable示例程式碼

<pre name="code" class="csharp">Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->//方法一
foreach (System.Collections.DictionaryEntry de in myHashtable)
{
  //注意HastTable記憶體儲的預設型別是object,需要進行轉換才可以輸出
  Console.WriteLine(de.Key.ToString());
  Console.WriteLine(de.Value.ToString());
}
 
 
//方法二
System.Collections.IDictionaryEnumerator enumerator = myHashtable.GetEnumerator();
 
while (enumerator.MoveNext())
{
  Console.WriteLine(enumerator.Key);    // Hashtable關健字
  Console.WriteLine(enumerator.Value);   // Hashtable值
}

三、字典Dictionary

Dictionary<Tkey,Tvalue>是Hastbale的泛型實現。

<span style="font-size:18px;">Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->//遍歷鍵
foreach (string key in myDictionary.Keys)
{
  //遍歷某鍵的值
  foreach (string val in myDictionary[key])
  {
 
  }
}</span>

由於 Dictionary 是鍵和值的集合,因此元素型別並非鍵型別或值型別。相反,元素型別是鍵型別和值型別的 KeyValuePair 。

<span style="font-size:18px;">字典遍歷示例 
 
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->foreach (KeyValuePair<string,string> kvp in myDictionary)
{
  string key = kvp.Key;//key包含了字典裡的鍵
  for (int i = 0; i < kvp.Value.Count; i++)
  {
    Response.Write(kvp.Value[i]);
  }
}</span>

示例 :

程式碼

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->//定義一個<string,int>的Dictionary,讓它的值進行新增(也可以用Add方法)
Dictionary<string,int> dic = new Dictionary<string,int>();
 
//新增兩個鍵為"成績1","成績2";併為它們的值賦為0
dic["成績1"] = 0;
dic["成績2"] = 0;
 
// 把這兩個值分別加1
dic["成績1"]++;
dic["成績2"]++;

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援我們。如有錯誤或未考慮完全的地方,望不吝賜教。