【问题标题】:Difference between Dictionary and Hashtable [duplicate]字典和哈希表之间的区别[重复]
【发布时间】:2010-10-26 23:22:33
【问题描述】:

可能重复:
Why Dictionary is preferred over hashtable in C#?

Dictionary 和 Hashtable 有什么区别。如何决定使用哪一个?

【问题讨论】:

  • 希望回答这个question给你一个很好的答案
  • 看来这个问题应该作为一个副本关闭,并且它的答案与其中一个副本合并。
  • 虽然与java语言相关,但this线程值得一读,了解HashMapHashTable的区别。 C# 世界也几乎没有区别。

标签: c# collections


【解决方案1】:

简单地说,Dictionary<TKey,TValue> 是一个泛型类型,允许:

  • 静态类型(和编译时验证)
  • 不装箱使用

如果你是 .NET 2.0 或更高版本,你应该首选Dictionary<TKey,TValue>(以及其他通用集合)

一个微妙但重要的区别是Hashtable 支持单个写入线程的多个读取线程,而Dictionary 不提供线程安全。如果您需要通用字典的线程安全,您必须实现自己的同步或(在 .NET 4.0 中)使用 ConcurrentDictionary<TKey, TValue>

【讨论】:

  • 但是字典的实例方法不是线程安全的,不像哈希表
【解决方案2】:

字典是有类型的(所以值类型不需要装箱),哈希表不是(所以值类型需要装箱)。 Hashtable 具有比字典恕我直言更好的获取值的方法,因为它始终知道该值是一个对象。虽然如果您使用的是 .NET 3.5,很容易为字典编写扩展方法以获得类似的行为。

如果每个键需要多个值,请在此处查看我的 MultiValueDictionary 源代码: multimap in .NET

【讨论】:

  • 对于每个键的多个值:在 .NET 3.5 中,您还可以考虑实现 ILookup<TKey,TValue>(这是多映射接口)。不幸的是,默认的具体实现是不可变的,但很容易重新实现(或添加到您的 MultiValueDictionary)。在 MiscUtil (EditableLookup) 中有一个简单的例子
  • 确实不错,我忘记了那个界面。我查看了 BCL 中的实现,但它确实是不可变的,因此对于日常多值使用几乎没有用;)。我会添加接口。
  • 嗯,ILookup有一个问题:它还实现了一个枚举器,这与字典枚举器不同。当在多值字典上使用 Linq 运算符时,它不能选择使用哪个枚举器,因为它也可以使用 IEnumerable>,即使 ILookup 是显式实现的......这使得它更难使用字典,因为它需要明确的类型规范。
  • MultiDictionary 也出现在 PowerCollections 中:www.wintellect.com/powercollections.aspx
【解决方案3】:

Hashtable 类是一种特定类型的字典类,它使用整数值(称为散列)来帮助存储其键。 Hashtable 类使用哈希来加快在集合中搜索特定键的速度。 .NET 中的每个对象都派生自 Object 类。此类支持 GetHash 方法,该方法返回唯一标识对象的整数。 Hashtable 类通常是一个非常有效的集合。 Hashtable 类的唯一问题是它需要一点开销,而且对于小型集合(少于 10 个元素),开销会影响性能。

必须考虑两者之间的一些特殊区别:

HashTable:是非泛型集合,这个开销最大 集合是它会自动为您的价值观和 为了获得您的原始价值,您需要执行拆箱, 这些会降低您的应用程序性能作为惩罚。

字典:这是集合的通用类型,其中没有隐式 装箱,因此无需拆箱,您将始终得到您的原件 您存储的值,因此它将改善您的应用程序 性能。

第二个显着的区别是:

如果您试图从哈希表中访问一个值 不存在的键将返回null。但在 字典它会给你 KeyNotFoundException。

【讨论】:

  • 我的 cmets 来自 MCTS 2.0 书,它得到了 -ve 代表......多么讽刺!!!! :D
  • 不是很讽刺...... Hashtable 和 Dictionary 都是基于这种方法,所以它无论如何都不能回答在它们之间进行选择的问题。
  • 真正具有讽刺意味的是,我正在阅读同一本 MCTS 书,对更喜欢哪一本书感到非常困惑,将其发布在这里并得到了与我刚刚以您的答案形式阅读的相同文本! ! :) 感谢您回复 nyways..
【解决方案4】:

HashTable 和 Dictionary 之间还有一个重要的区别。如果您使用索引器从 HashTable 中获取值,则 HashTable 将为不存在的项目成功返回 null,而如果您尝试使用 Dictionary

【讨论】:

    【解决方案5】:

    ILookup 接口在 .net 3.5 中与 linq 一起使用。

    HashTable 是弱类型的基类;词典库 抽象类是强类型的,并在内部使用 HashTable。

    我发现Dictionary有一个奇怪的地方,当我们在Dictionary中添加多个条目时,条目的添加顺序保持不变。因此,如果我在 Dictionary 上应用 foreach,我将按照插入它们的顺序获取记录。

    然而,对于普通的 HashTable,情况并非如此,因为当我在 Hashtable 中添加相同的记录时,不会保持顺序。据我所知,Dictionary 是基于 Hashtable 的,如果这是真的,为什么我的 Dictionary 保持顺序而 HashTable 没有?

    至于为什么它们的行为不同,这是因为通用字典实现了一个哈希表,但不是基于 System.Collections.Hashtable。通用字典实现基于从列表中分配键值对。然后使用哈希表存储桶对它们进行索引以进行随机访问,但是当它返回一个枚举器时,它只是按顺序遍历列表 - 只要不重复使用条目,这就是插入的顺序。

    shiv govind Birlasoft.:)

    【讨论】:

      【解决方案6】:

      让我们举一个例子来解释哈希表和字典之间的区别。

      这是一个实现hashtable的方法

      public void MethodHashTable()
      {
          Hashtable objHashTable = new Hashtable();
          objHashTable.Add(1, 100);    // int
          objHashTable.Add(2.99, 200); // float
          objHashTable.Add('A', 300);  // char
          objHashTable.Add("4", 400);  // string
      
          lblDisplay1.Text = objHashTable[1].ToString();
          lblDisplay2.Text = objHashTable[2.99].ToString();
          lblDisplay3.Text = objHashTable['A'].ToString();
          lblDisplay4.Text = objHashTable["4"].ToString();
      
      
          // ----------- Not Possible for HashTable ----------
          //foreach (KeyValuePair<string, int> pair in objHashTable)
          //{
          //    lblDisplay.Text = pair.Value + " " + lblDisplay.Text;
          //}
      }
      

      以下是字典

        public void MethodDictionary()
        {
          Dictionary<string, int> dictionary = new Dictionary<string, int>();
          dictionary.Add("cat", 2);
          dictionary.Add("dog", 1);
          dictionary.Add("llama", 0);
          dictionary.Add("iguana", -1);
      
          //dictionary.Add(1, -2); // Compilation Error
      
          foreach (KeyValuePair<string, int> pair in dictionary)
          {
              lblDisplay.Text = pair.Value + " " + lblDisplay.Text;
          }
        }
      

      【讨论】:

      • 请注意.....您可以枚举 Hashtable 属性,如下所述:msdn.microsoft.com/en-us/library/…。您必须使用 DictionaryEntry 作为变量,然后它可以提供键和值对象。
      • 极好的答案,您也可以使用 DictionaryEntry 枚举 Hashtable。例如:foreach(DictionaryEntry dnty in objHashTable ){lblDisplay.Text= dnty.Value + " " +dnty.Key}
      • //循环hastable foreach(objHashTable中的DictionaryEntry条目){ Console.WriteLine("{0}, {1}", entry.Key, entry.Value); }
      【解决方案7】:

      想加个区别:

      尝试访问不存在的键会在字典中出现运行时错误,但在哈希表中没有问题,因为它返回 null 而不是错误。

      例如

             //No strict type declaration
              Hashtable hash = new Hashtable();
              hash.Add(1, "One");
              hash.Add(2, "Two");
              hash.Add(3, "Three");
              hash.Add(4, "Four");
              hash.Add(5, "Five"); 
              hash.Add(6, "Six");
              hash.Add(7, "Seven");
              hash.Add(8, "Eight");
              hash.Add(9, "Nine");
              hash.Add("Ten", 10);// No error as no strict type
      
              for(int i=0;i<=hash.Count;i++)//=>No error for index 0
              {
                  //Can be accessed through indexers
                  Console.WriteLine(hash[i]);
              }
              Console.WriteLine(hash["Ten"]);//=> No error in Has Table
      

      这里键 0 和键“十”没有错误(注意:t 很小)

      //Strict type declaration
              Dictionary<int,string> dictionary= new Dictionary<int, string>();
              dictionary.Add(1, "One");
              dictionary.Add(2, "Two");
              dictionary.Add(3, "Three");
              dictionary.Add(4, "Four");
              dictionary.Add(5, "Five");
              dictionary.Add(6, "Six");
              dictionary.Add(7, "Seven");
              dictionary.Add(8, "Eight");
              dictionary.Add(9, "Nine");
              //dictionary.Add("Ten", 10);// error as only key, value pair of type int, string can be added
      
              //for i=0, key doesn't  exist error
              for (int i = 1; i <= dictionary.Count; i++)
              {
                  //Can be accessed through indexers
                  Console.WriteLine(dictionary[i]);
              }
              //Error : The given key was not present in the dictionary.
              //Console.WriteLine(dictionary[10]);
      

      键 0 和键 10 出现此处错误,因为字典中不存在两者,运行时错误,同时尝试访问。

      【讨论】:

      猜你喜欢
      • 2011-01-04
      • 2011-07-07
      • 2011-05-24
      • 2012-04-03
      • 2015-02-20
      • 1970-01-01
      • 2010-11-11
      • 2017-10-17
      • 2016-11-03
      相关资源
      最近更新 更多