在大多数编程语言中,字典比哈希表更受青睐。背后的原因是什么?
Dictionary
是的实现Hashtable
。
HashTable
。当他们在语言中添加泛型时,他们称为泛型版本Dictionary
。两者都是哈希表。
在大多数编程语言中,字典比哈希表更受青睐。背后的原因是什么?
Dictionary
是的实现Hashtable
。
HashTable
。当他们在语言中添加泛型时,他们称为泛型版本Dictionary
。两者都是哈希表。
Answers:
对于它的价值,字典在概念上是一个哈希表。
如果您的意思是“为什么我们使用Dictionary<TKey, TValue>
类而不是Hashtable
类?”,那么这是一个简单的答案:Dictionary<TKey, TValue>
是泛型类型,Hashtable
不是。这意味着您可以使用来获得类型安全性Dictionary<TKey, TValue>
,因为您不能在其中插入任何随机对象,也不必强制转换取出的值。
有趣的是,Dictionary<TKey, TValue>
.NET Framework中的实现基于Hashtable
,您可以从其源代码中的此注释中看出:
通用字典是从Hashtable的来源复制而来的
HashTable
(class)和Dictionary
(class)都是哈希表(concept),但是a HashTable
不是a Dictionary
,也不是Dictionary
a HashTable
。它们以非常相似的方式使用,并且Dictionary<Object,Object>
可以以与a相同的无类型方式起作用HashTable
,但是它们不直接共享任何代码(尽管部分可能以非常相似的方式实现)。
Dictionary
<<< >>> Hashtable
差异:
Synchronized()
KeyValuePair
<<< >>>枚举项目:DictionaryEntry
Dictionary
/ Hashtable
相似之处:
GetHashCode()
方法相似的 .NET集合(代替字典和哈希表使用的候选人):
ConcurrentDictionary
- 线程安全(可以同时从多个线程安全地访问)HybridDictionary
- 优化的性能(适用于少量物品,也适用于许多物品)OrderedDictionary
-可以通过int索引(按添加项目的顺序)访问值SortedDictionary
- 自动排序的项目StringDictionary
-强类型化并针对字符串进行了优化StringDictionary
... btw的+1 StringDictionary
与Dictionary<string, string>
使用默认构造函数时不同。
因为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
在内部实现为哈希表,因此从技术上讲,它的工作方式相同。
仅供参考:在.NET中,Hashtable
线程安全性可用于多个读取器线程和单个写入线程,而在Dictionary
公共静态成员中则是线程安全的,但不能保证任何实例成员都是线程安全的。
因此,我们必须将所有词典重新更改Hashtable
为。
ConcurrentDictionary
该类,该类具有实现为线程安全的所有公共/受保护方法。如果您不需要支持旧平台,则可以替换Hashtable
多线程代码中的代码:msdn.microsoft.com/en-us/library/dd287191.aspx
在.NET之间的差异Dictionary<,>
,并HashTable
主要是前者是一个泛型类型,所以你在静态类型检查(并降低拳击而言仿制药的所有好处,但这不是大如人们往往认为在性能方面-拳击有一定的内存成本)。
人们说字典与哈希表相同。
这不一定是真的。哈希表是实现字典的一种方法。那是一个典型的实例,它可能是.NET中Dictionary
该类中的默认实例,但根据定义,它并不是唯一的实例。
您同样可以使用链表或搜索树来实现字典,只是效率不高(对于效率的某种度量)。
Dictionary<K,V>
。IDictionary<K,V>
可能是什么,但:)
Collections
&Generics
对于处理对象组很有用。在.NET中,所有collections对象都位于该接口下IEnumerable
,而该接口又具有ArrayList(Index-Value))
&HashTable(Key-Value)
。在.NET Framework 2.0之后,ArrayList
&HashTable
替换为List
&Dictionary
。现在,Arraylist
&HashTable
不再在当今的项目中使用。
来到之间的区别HashTable
和Dictionary
,Dictionary
是通用的,其中如Hastable
不通用。我们可以向添加任何类型的对象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);
}
}
}
字典:
如果我们试图找到一个不存在的键,它将返回/抛出异常。
它比哈希表更快,因为没有装箱和拆箱。
仅公共静态成员是线程安全的。
字典是一种通用类型,这意味着我们可以将其与任何数据类型一起使用(创建时,必须同时指定键和值的数据类型)。
例: Dictionary<string, string> <NameOfDictionaryVar> =
new Dictionary<string, string>();
Dictionay是Hashtable的类型安全实现,Keys
并且Values
具有强类型。
哈希表:
如果我们尝试查找不存在的键,则返回null。
它比字典慢,因为它需要装箱和拆箱。
哈希表中的所有成员都是线程安全的,
哈希表不是通用类型,
Hashtable是松散类型的数据结构,我们可以添加任何类型的键和值。
Dictionary.TryGetValue
MSDN上有关使用C#进行数据结构的广泛检查的内容指出,冲突解决策略也存在差异 :
Hashtable类使用一种称为rehashing的技术。
重新哈希的工作方式如下:有一组哈希不同的函数H 1 ... H n,当从哈希表插入或检索项目时,最初使用H 1哈希函数。如果这导致了碰撞,H 2试图代替,并开始长达^ h ñ如果需要的话。
字典使用称为链接的技术。
通过重新哈希,在发生冲突的情况下,可以重新计算哈希,并尝试与哈希相对应的新插槽。但是,通过链接,可以使用辅助数据结构来保存任何冲突。具体来说,字典中的每个插槽都有一个映射到该存储桶的元素数组。在发生碰撞的情况下,碰撞元素位于铲斗列表的前面。
从.NET Framework 3.5开始HashSet<T>
,Dictionary<TKey, TValue>
如果只需要键而不需要值,则还提供了的所有优点。
因此,如果您使用a Dictionary<MyType, object>
并始终将其值设置null
为模拟类型安全哈希表,则应考虑切换到HashSet<T>
。
注意,MSDN说:“ Dictionary <(Of <(TKey,TValue>)>)类被实现为哈希表 ”,而不是“ Dictionary <(Of <(TKey,TValue>)>)类被实现为HashTable ”。
字典不是作为HashTable实现的,而是按照哈希表的概念实现的。该实现与HashTable类无关,因为使用了泛型,尽管Microsoft在内部可以使用相同的代码,并用TKey和TValue替换Object类型的符号。
在.NET 1.0中,泛型不存在。这是HashTable和ArrayList最初开始的地方。
哈希表:
存储在堆中时,键/值将转换为对象(装箱)类型。
从堆读取时,键/值需要转换为所需的类型。
这些操作非常昂贵。我们需要尽可能避免装箱/拆箱。
字典: HashTable的通用变体。
没有装箱/拆箱。无需转换。
Hashtable对象由包含集合元素的存储桶组成。存储桶是哈希表中元素的虚拟子组,与大多数集合相比,存储桶使搜索和检索更加轻松快捷。
Dictionary类具有与Hashtable类相同的功能。特定类型的字典(对象以外的字典)比哈希表具有更好的性能对于值类型,因为哈希表的元素是对象类型,因此,如果存储或检索值类型,则装箱和拆箱通常会发生。
进一步阅读:哈希表和字典集合类型
另一个重要的区别是Hashtable是线程安全的。Hashtable具有内置的多个读取器/单个写入器(MR / SW)线程安全性,这意味着Hashtable允许ONE写入器与多个读取器一起使用而不会锁定。
对于Dictionary,没有线程安全性;如果需要线程安全,则必须实现自己的同步。
详细说明:
Hashtable通过该
Synchronized
属性提供了一些线程安全性,该属性返回围绕该集合的线程安全包装器。包装器通过在每个添加或删除操作上锁定整个集合来工作。因此,每个试图访问该集合的线程都必须等待其轮换获得一个锁。这是不可扩展的,并且可能导致大型集合的性能显着下降。而且,该设计也没有完全免受竞争条件的影响。.NET Framework 2.0集合类(如
List<T>, Dictionary<TKey, TValue>
)等不提供任何线程同步;在多个线程上同时添加或删除项目时,用户代码必须提供所有同步
如果需要类型安全性和线程安全性,请在.NET Framework中使用并发集合类。在这里进一步阅读。
另一个区别是,当我们在“字典”中添加多个条目时,将保持添加条目的顺序。当我们从Dictionary中检索项目时,我们将以插入它们的相同顺序获得记录。而Hashtable不会保留插入顺序。
Hashset
使用情况下,保证MR / SW线程安全。我认为它可能是完全MR / SW安全的,但是安全地处理删除操作会大大增加MR / SW安全的费用。尽管Dictionary
在无删除方案中本可以以最低的成本提供MR / SW安全性,但我认为MS希望避免将无删除方案视为“特殊”情况。
Dictionary<>
是通用类型,因此类型安全。
您可以在HashTable中插入任何值类型,这有时可能会引发异常。但是Dictionary<int>
将仅接受整数值,并且类似地Dictionary<string>
将仅接受字符串。
因此,最好使用Dictionary<>
代替HashTable
。
在大多数编程语言中,字典比哈希表更受青睐
我认为这不一定是正确的,大多数语言都有一种或另一种,这取决于他们喜欢的术语。
但是,在C#中,(对我而言)明显的原因是C#HashTables和System.Collections命名空间的其他成员已经过时了。它们存在于c#V1.1中。它们已从C#2.0中由System.Collections.Generic命名空间中的Generic类替换。
根据我使用.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。