为什么Dictionary优先于C#中的Hashtable?

问题描述 投票:1301回答:19

在大多数编程语言中,字典比散列表更受欢迎。这背后的原因是什么?

c# .net vb.net data-structures
19个回答
1512
投票

对于它的价值,词典(概念上)是一个哈希表。

如果你的意思是“为什么我们使用Dictionary<TKey, TValue>类而不是Hashtable类?”,那么这是一个简单的答案:Dictionary<TKey, TValue>是泛型类型,Hashtable不是。这意味着您可以使用Dictionary<TKey, TValue>获得类型安全性,因为您无法在其中插入任何随机对象,并且您不必强制转换所取出的值。

有趣的是,.NET Framework中的Dictionary<TKey, TValue>实现基于Hashtable,您可以从源代码中的注释中看出:

通用词典是从Hashtable的源代码复制而来的

Source


13
投票

自.NET Framework 3.5以来,还有一个HashSet<T>,它提供了Dictionary<TKey, TValue>的所有优点,如果你只需要键和没有值。

因此,如果您使用Dictionary<MyType, object>并始终将值设置为null来模拟类型安全哈希表,您应该考虑切换到HashSet<T>


12
投票

Hashtable是一个松散类型的数据结构,因此您可以将任何类型的键和值添加到HashtableDictionary类是类型安全的Hashtable实现,键和值是强类型的。创建Dictionary实例时,必须为键和值指定数据类型。


11
投票

请注意,MSDN说:“Dictionary <(Of <(TKey,TValue>)>)类实现为哈希表”,而不是“Dictionary <(Of <(TKey,TValue>)>)类实现为HashTable”

Dictionary不是作为HashTable实现的,而是按照哈希表的概念实现的。由于使用了Generics,实现与HashTable类无关,尽管内部Microsoft可能使用了相同的代码并用TKey和TValue替换了Object类型的符号。

在.NET 1.0中,Generics不存在;这是HashTable和ArrayList最初开始的地方。


8
投票

Hashtable对象由包含集合元素的存储桶组成。存储桶是Hashtable中虚拟的元素子组,与大多数集合相比,它使搜索和检索更容易,更快捷。

Dictionary类与Hashtable类具有相同的功能。特定类型的字典(除了Object)具有比值类型的Hashtable更好的性能,因为Hashtable的元素是Object类型,因此,如果存储或检索值类型,通常会发生装箱和取消装箱。

进一步阅读:Hashtable and Dictionary Collection Types


8
投票

哈希表:

键/值将在存储到堆中时转换为对象(装箱)类型。

在从堆读取时,需要将键/值转换为所需的类型。

这些操作非常昂贵。我们需要尽可能避免装箱/拆箱。

字典:HashTable的通用变体。

没有拳击/拆箱。无需转换。


6
投票

另一个重要的区别是Hashtable是线程安全的。 Hashtable具有内置的多个读取器/单个写入器(MR / SW)线程安全性,这意味着Hashtable允许一个编写器与多个读取器一起使用而无需锁定。

在Dictionary的情况下,没有线程安全;如果您需要线程安全,则必须实现自己的同步。

进一步阐述:

Hashtable通过Synchronized属性提供一些线程安全性,该属性返回集合周围的线程安全包装器。包装器通过在每次添加或删除操作时锁定整个集合来工作。因此,尝试访问集合的每个线程必须等待轮到一个锁。这不可扩展,可能会导致大型集合的性能显着下降。此外,该设计并未完全免受竞争条件的影响。

List<T>, Dictionary<TKey, TValue>等.NET Framework 2.0集合类不提供任何线程同步;用户代码必须在多个线程上同时添加或删除项目时提供所有同步

如果您需要类型安全性以及线程安全性,请在.NET Framework中使用并发集合类。进一步阅读here

另一个区别是,当我们在Dictionary中添加多个条目时,将保留添加条目的顺序。当我们从Dictionary中检索项目时,我们将按照插入它们的相同顺序获取记录。而Hashtable不保留插入顺序。


5
投票

我能想到的另一个不同之处是:

我们不能将Dictionary <KT,VT>(泛型)与Web服务一起使用。原因是没有Web服务标准支持泛型标准。


5
投票

Dictionary<>是一种通用类型,因此它的类型安全。

您可以在HashTable中插入任何值类型,这有时会引发异常。但是Dictionary<int>只接受整数值,同样Dictionary<string>只接受字符串。

因此,最好使用Dictionary<>而不是HashTable


0
投票

在大多数编程语言中,字典比散列表更受欢迎

我不认为这一定是正确的,大多数语言都有其中一种,具体取决于terminology they prefer

但是,在C#中,明确的原因(对我而言)是C#HashTables和System.Collections命名空间的其他成员在很大程度上已经过时了。它们出现在c#V1.1中。它们已由System.Collections.Generic命名空间中的Generic类从C#2.0替换。


-3
投票

根据我使用.NET Reflector看到的:

[Serializable, ComVisible(true)]
public abstract class DictionaryBase : IDictionary, ICollection, IEnumerable
{
    // Fields
    private Hashtable hashtable;

    // Methods
    protected DictionaryBase();
    public void Clear();
.
.
.
}
Take note of these lines
// Fields
private Hashtable hashtable;

所以我们可以确定DictionaryBase在内部使用HashTable。


603
投票

Dictionary <<< >>> Hashtable差异:

  • 通用<<< >>>非通用
  • 需要自己的线程同步<<< >>>通过Synchronized()方法提供线程安全版本
  • 枚举项目:KeyValuePair <<< >>>枚举项目:DictionaryEntry
  • 较新(>。NET 2.0)<<< >>>较旧(自.NET 1.0起)
  • 在System.Collections.Generic <<< >>>在System.Collections中
  • 请求不存在的键抛出异常<<< >>>对不存在的键的请求返回null
  • 对于值类型,<<< >>>可能会更慢一点(需要装箱/取消装箱)

Dictionary / Hashtable的相似之处:

  • 两者都是内部哈希表==根据键快速访问多项数据
  • 两者都需要不可变和唯一的密钥
  • 两者的钥匙都需要自己的GetHashCode()方法

类似的.NET集合(候选使用而不是Dictionary和Hashtable):

  • ConcurrentDictionary - 线程安全(可以同时从多个线程安全地访问)
  • HybridDictionary - 优化的性能(少数项目和许多项目)
  • OrderedDictionary - 可以通过int索引访问值(按添加项目的顺序)
  • SortedDictionary - 项目自动排序
  • StringDictionary - 强类型和优化字符串

175
投票

因为Dictionary是一个泛型类(Dictionary<TKey, TValue>),所以访问它的内容是类型安全的(即你不需要像Object那样从Hashtable强制转换)。

相比

var customers = new Dictionary<string, Customer>();
...
Customer customer = customers["Ali G"];

var customers = new Hashtable();
...
Customer customer = customers["Ali G"] as Customer;

但是,Dictionary在内部实现为哈希表,因此从技术上讲它的工作方式相同。


84
投票

仅供参考:在.NET中,Hashtable可供多个读取器线程和单个写入线程使用,但在Dictionary中,公共静态成员是线程安全的,但不保证任何实例成员都是线程安全的。

因此,我们不得不将所有词典改回Hashtable


67
投票

在.NET中,Dictionary<,>HashTable之间的区别主要在于前者是泛型类型,因此您可以在静态类型检查方面获得泛型的所有好处(并减少拳击,但这并不像人们倾向于那么大从性能的角度考虑 - 虽然拳击有一定的记忆成本。


32
投票

人们说词典与哈希表相同。

这不一定是真的。哈希表是实现字典的一种方法。这是典型的一个,它可能是Dictionary类中.NET中的默认值,但它不是定义中唯一的一个。

你也可以使用链表或搜索树来实现字典,它只是效率不高(对某些效率指标而言)。


21
投票

CollectionsGenerics可用于处理一组物体。在.NET中,所有集合对象都在IEnumerable接口下,后者又有ArrayList(Index-Value))HashTable(Key-Value)。在.NET framework 2.0之后,ArrayListHashTableListDictionary取代。现在,ArraylistHashTable在现今的项目中不再使用了。

HashTableDictionary之间存在差异,Dictionary是通用的,因为Hastable不是Generic。我们可以向HashTable添加任何类型的对象,但在检索时我们需要将其强制转换为所需的类型。所以,它不是类型安全的。但是对于dictionary,在声明自己时我们可以指定键和值的类型,因此在检索时不需要进行强制转换。

我们来看一个例子:

哈希表

class HashTableProgram
{
    static void Main(string[] args)
    {
        Hashtable ht = new Hashtable();
        ht.Add(1, "One");
        ht.Add(2, "Two");
        ht.Add(3, "Three");
        foreach (DictionaryEntry de in ht)
        {
            int Key = (int)de.Key; //Casting
            string value = de.Value.ToString(); //Casting
            Console.WriteLine(Key + " " + value);
        }

    }
}

字典,

class DictionaryProgram
{
    static void Main(string[] args)
    {
        Dictionary<int, string> dt = new Dictionary<int, string>();
        dt.Add(1, "One");
        dt.Add(2, "Two");
        dt.Add(3, "Three");
        foreach (KeyValuePair<int, String> kv in dt)
        {
            Console.WriteLine(kv.Key + " " + kv.Value);
        }
    }
}

16
投票

字典:

  • 如果我们试图找到一个不存在的密钥,它会返回/抛出异常。
  • 它比Hashtable更快,因为没有装箱和拆箱。
  • 只有公共静态成员是线程安全的。
  • Dictionary是一种泛型类型,这意味着我们可以将它与任何数据类型一起使用(创建时,必须指定键和值的数据类型)。 示例:Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();
  • Dictionay是Hashtable的类型安全实现,KeysValues是强类型的。

哈希表:

  • 如果我们试图找到一个不存在的密钥,它将返回null。
  • 它比字典慢,因为它需要装箱和拆箱。
  • Hashtable中的所有成员都是线程安全的,
  • Hashtable不是通用类型,
  • Hashtable是松散类型的数据结构,我们可以添加任何类型的键和值。

15
投票

MSDN上的Extensive Examination of Data Structures Using C#文章指出冲突解决策略也存在差异:

Hashtable类使用称为rehashing的技术。

Rehashing的工作方式如下:有一组哈希不同的函数,H1 ... Hn,当从哈希表中插入或检索项时,最初使用H1哈希函数。如果这会导致碰撞,则尝试使用H2,如果需要,则转到Hn。

字典使用称为链接的技术。

通过重新散列,在发生冲突时,重新计算散列,并尝试对应于散列的新槽。然而,通过链接,利用辅助数据结构来保持任何冲突。具体来说,Dictionary中的每个插槽都有一个映射到该存储桶的元素数组。如果发生碰撞,碰撞元素将被添加到桶的列表中。

© www.soinside.com 2019 - 2024. All rights reserved.