在大多数编程语言中,字典比哈希表更受欢迎。这背后的原因是什么?
当前回答
差异
Dictionary |
Hashtable |
---|---|
Generic | Non-Generic |
Needs own thread synchronization | Offers thread safe version through Synchronized() method |
Enumerated item: KeyValuePair |
Enumerated item: DictionaryEntry |
Newer (> .NET 2.0) | Older (since .NET 1.0) |
is in System.Collections.Generic | is in System.Collections |
Request to non-existing key throws exception | Request to non-existing key returns null |
potentially a bit faster for value types | bit slower (needs boxing/unboxing) for value types |
相似之处:
两者都是内部哈希表==根据关键字快速访问许多项数据两者都需要不可变和唯一的密钥两者的键都需要自己的GetHashCode()方法
其他.NET集合:
(要使用的候选项,而不是字典和哈希表)
ConcurrentDictionary-线程安全(可以从多个线程同时安全访问)HybridDictionary-优化的性能(适用于少数项目,也适用于许多项目)OrderedDictionary-值可以通过int索引访问(按添加项的顺序)SortedDictionary-自动排序的项目StringDictionary-强类型并针对字符串进行了优化(现在不推荐使用Dictionary<string,string>)
其他回答
人们说字典和哈希表是一样的。
这不一定是真的。哈希表是实现字典的一种方法。这是一个典型的例子,它可能是.NET中Dictionary类中的默认例子,但根据定义,它不是唯一的例子。
你同样可以使用链接列表或搜索树来实现字典,但它并没有那么高效(对于一些高效的度量)。
注意,文档中说:“Dictionary<(Of<(TKey,TValue>)>)类是作为哈希表实现的”,而不是“Dictionary<(Of<(TKey,TValue>)>类是作为HashTable实现的”
字典没有实现为哈希表,但它是按照哈希表的概念实现的。由于使用了泛型,该实现与HashTable类无关,尽管微软内部可能使用了相同的代码,并用TKey和TValue替换了Object类型的符号。
在.NET 1.0中,泛型不存在;这是HashTable和ArrayList最初开始的地方。
另一个重要的区别是Hashtable是线程安全的。Hashtable具有内置的多读取器/单写入器(MR/SW)线程安全性,这意味着Hashtable允许一个写入器与多个读取器一起使用,而无需锁定。
在Dictionary的情况下,没有线程安全;如果需要线程安全,则必须实现自己的同步。
进一步阐述:
Hashtable通过Synchronized属性提供了一些线程安全性,该属性返回集合周围的线程安全包装。包装器通过在每次添加或删除操作时锁定整个集合来工作。因此,每个试图访问集合的线程都必须等待轮到它获取一个锁。这是不可扩展的,可能会导致大型集合的性能显著下降。此外,该设计没有完全保护免受比赛条件的影响。.NET Framework 2.0集合类(如List<T>、Dictionary<TKey、TValue>等)不提供任何线程同步;当在多个线程上同时添加或删除项时,用户代码必须提供所有同步
如果需要类型安全和线程安全,请在.NETFramework中使用并发集合类。在这里进一步阅读。
另外一个区别是,当我们在字典中添加多个条目时,条目的添加顺序保持不变。当我们从字典中检索条目时,我们将按照插入它们的相同顺序获取记录。而Hashtable不保留插入顺序。
自.NET Framework 3.5以来,还有一个HashSet<T>,它提供了字典<TKey,TValue>的所有优点,如果您只需要键而不需要值。
因此,如果您使用Dictionary<MyType,object>并始终将值设置为null以模拟类型安全哈希表,您可能应该考虑切换到HashSet<T>。
仅供参考:在.NET中,Hashtable是线程安全的,可供多个读线程和一个写线程使用,而在Dictionary中,公共静态成员是线程安全,但不能保证任何实例成员都是线程安全。
因此,我们不得不将所有词典改回Hashtable。
推荐文章
- 不区分大小写列表搜索
- 'throw'和'throw new Exception()'的区别
- 不能在lambda表达式中使用ref或out参数
- c# int到字节[]
- 如何跟踪log4net问题
- 将WPF组合框绑定到自定义列表
- foreach vs somlist . foreach (){}
- 为什么try{…}最后{…}好;尝试{…} catch{}坏?
- c# 8用多种情况切换表达式,结果相同
- 在没有事件源注册的情况下写入Windows应用程序事件日志
- 并发HashSet<T>在。net框架?
- 从控制器内获得控制器和动作名称?
- _ViewStart的位置和方式。CSHTML布局文件链接?
- 新建T()
- 如何将枚举绑定到WPF中的组合框控件?