在大多数编程语言中,字典比哈希表更受欢迎。这背后的原因是什么?
>这不一定是真的。哈希表是字典的实现。这是一个典型的例子,它可能是.NET中的默认值,但根据定义它不是唯一的一个。我不确定这是否是ECMA标准所要求的,但是MSDN文档非常清楚地将其作为哈希表实现。它们甚至提供了sortedList类,以便在选择更合理的时候使用。
@promit我一直认为Dictionary 是Hashtable 的实现。
我认为原因是,在字典中,你可以定义键的类型和你自己的值。哈希表只能获取对象并基于哈希(from object.getHashCode())保存对。
@丹,你的说法完全错了…哈希表只包含每个键的一个实例,搜索不会生成多个条目;如果要将多个值与每个键关联,请将哈希表值设置为值列表。没有"字典"这样的数据结构…字典只是一些库用于哈希表的名称。例如,C的非通用哈希表称为Hashtable 。当他们将泛型添加到语言中时,他们称之为通用版本Dictionary 。两者都是哈希表。
@丹,你的说法错了…哈希表(en.wikipedia.org/wiki/hash_table)是一个字典的特殊实现,也就是一个关联数组(en.wikipedia.org/wiki/associative_array),而且作为一个字典,每个键只包含一个实例,搜索不会产生多个条目;如果要将多个值与每个键关联,请创建哈希表。值值的列表。NET字典和哈希表类都是哈希表。
你想要一个特定的定义吗?即使没有疑问。哈希表是一个充满哈希的表。现在,这意味着2个键不能生成相同的哈希值的部分是什么?如果你把你的头从你的C和停止使用wiki来支持你的主张,你可能会学会如何沟通。
问题的原始标题是C特定的。我已经恢复了"在C"的头衔。
不要与hashset混淆,与Hashtable 不同,hashset是通用的。
就其价值而言,字典(概念上)是一个哈希表。
如果您的意思是"为什么我们要使用Dictionary 类而不是Hashtable 类?"这是一个简单的答案:Dictionary 是一个通用类型,Hashtable 不是。这意味着您可以使用Dictionary 获得类型安全性,因为您不能在其中插入任何随机对象,也不必强制转换所取的值。
有趣的是,.NET框架中的Dictionary 实现是基于Hashtable 的,正如您在其源代码中看到的注释所示:
The generic Dictionary was copied from Hashtable's source
来源
此外,由于没有装箱/拆箱,通用集合速度更快。
不确定上面语句的哈希表,但对于arraylist vs list它是真的
hashtable使用对象在内部保存东西(只有非常规方式),因此它也必须装箱/拆箱。
如果字典是通用的,那么说哈希表是字典是否更准确?整个"正方形都是长方形,但不是所有的长方形都是正方形"的东西?
@brianj:"哈希表"(两个词)是这种结构的计算机科学术语;字典是一种具体的实现。哈希表大致对应于dictionary(尽管接口略有不同),但两者都是哈希表概念的实现。当然,为了进一步混淆问题,有些语言称它们的哈希表为"字典"(例如python),但正确的cs术语仍然是哈希表。
@为了确保我能正确理解你,HashTable 数据结构是一个字典,它是一个哈希表(概念),对吧?
@brianj:EDOCX1(class)和EDOCX1(class)都是散列表(concept),但是HashTable 不是Dictionary ,Dictionary 也不是HashTable 。它们以非常相似的方式使用,并且Dictionary 可以以与HashTable 相同的非类型化方式工作,但它们不直接共享任何代码(尽管部分可能以非常相似的方式实现)。
@迈克尔森还好。我现在明白了。谢谢你的澄清。
@brianj"如果字典是通用的,那么说哈希表是字典就更准确了吗?"--不,因为"通用"在编程语言中有特定的含义,与英语术语几乎没有关系。"泛型"类或方法是具有一个或多个类型参数的类或方法。
@Michealmadsen,我认为混淆的原因在于,除了c_之外,术语dictionary还被用作抽象数据类型,Hash Table 是具有特定运行时间的解决方案。此外,generic在c_之外也有一个含义,因此,如果您不知道c_,则"generic dictionary"可以解释为抽象数据结构。
只有公共静态成员在字典中是线程安全的,而所有成员在哈希表中是线程安全的。
字典支持的LINQ语句比哈希表多
@Michaelmadsen:如果Brian J所指的是C.S.的(大写)"通用"概念,那么你对他的评论是正确的。在该概念中,类或方法可以对调用方指定的类型(顺便说一句,我相信这也是他真正想要的类型)进行操作。…
@但是,如果他指的是(小写)"一般"(如数据结构或算法比另一个更灵活/更低级别),那就不准确了。从这个意义上讲,.NET HashTable 比.NET Dictionary 更(小写)"通用",因此,如果代码大小/性能问题不是.NET Dictionary 的话,前者(在我的语句中和按照开发顺序)可能会重新实现为后者的包装器(在这种情况下,这也是一种非常常见的重构实践)。SIG发布了他们通常使用的内容。不是(框架级代码之外)。
上面汤姆的评论是不正确的,而且在他们没有完全混淆的地方,之前的评论已经提到了。
Dictionary <<<>Hashtable 差异:
通用的<<<>非通用
线程同步的需要自己的<<><Synchronized() 提供线程安全版本的方法,通
enumerated项目:KeyValuePair <<<>enumerated DictionaryEntry 项目:
新的(.net 2.0<><>)大(由于.NET 1.0)
在system.collections.generic<<<一>是集合系统。
现有的密钥请求不抛出异常的<<<>非现有的密钥请求到返回null
值类型是潜在的更快的比特位的<<<>慢(需要装箱/拆箱值类型)
Dictionary / Hashtable 相似:
无论是散列表=式快速访问关键数据,根据多个项目
独特的键和两个不变的需要
GetHashCode() 都需要自己的方法。
NET集合(类似的候选人而不是使用字典和哈希表):
ConcurrentDictionary 线程安全的(可以从几个线程安全的访问concurrently)
HybridDictionary 优化性能(在一些项目,也被许多项目)
OrderedDictionary 值可以通过数组索引(访问),在这项命令,分别。
自动SortedDictionary 项目类
强型和优化StringDictionary 弦乐
我们可以将ConcurrentDictionary(in.NET 4.0)用于线程安全。
@Guillaume86,这就是为什么您使用TryGetValue而不是msdn.microsoft.com/en-us/library/bb347013.aspx
+1对于StringDictionary …btw StringDictionary 在使用默认构造函数时与Dictionary 不同。
[email protected] /windowsdesktop/…包含一个observableConcurrentDictionary,它具有很好的FIR绑定和并发性。
很好的解释,你还列出了一些相似之处,以减少人们可能想到的问题。
stackoverflow.com/a/1089142/5035500,net-informations.com/faq/general/dictionary.htm,c-sharpcorner.com/blogs/…
因为Dictionary 是一个通用类(Dictionary ),所以访问它的内容是类型安全的(即,您不需要像处理Hashtable 那样从Object 强制转换)。
比较
1 2 3
var customers
= new Dictionary
< string , Customer
> ( ) ;
...
Customer customer
= customers
[ "Ali G" ] ;
到
1 2 3
var customers
= new Hashtable
( ) ;
...
Customer customer
= customers
[ "Ali G" ] as Customer
;
但是,Dictionary 在内部实现为哈希表,因此在技术上它的工作方式是相同的。
仅供参考:在.NET中,Hashtable 是线程安全的,可供多个读线程和单个写入线程使用,而在Dictionary 中,公共静态成员是线程安全的,但任何实例成员都不保证是线程安全的。
因此,我们不得不把所有的词典都改回Hashtable 。
乐趣。字典的源代码看起来更干净更快。最好使用字典并实现自己的同步。如果字典读取绝对需要是最新的,那么您只需同步访问字典的读/写方法。这将是一个很大的锁定,但它是正确的。
或者,如果你的阅读不一定是最新的,你可以把字典当作不变的。然后,您可以获取对字典的引用,并通过根本不同步读取来获得性能(因为它是不可变的,并且本质上是线程安全的)。要更新它,您需要在后台构建一个字典的完整更新副本,然后用interlocked.compareExchange交换引用(假设一个写入线程;多个写入线程需要同步更新)。
.NET 4.0添加了ConcurrentDictionary 类,该类实现了所有公共/受保护方法以保证线程安全。如果您不需要支持传统平台,这将允许您在多线程代码中替换Hashtable :msdn.microsoft.com/en-us/library/dd287191.aspx
匿名营救。冷静的回答。
我记得在从未从表中删除信息的场景中,hashtable是唯一一个读写线程安全的。如果读卡器在删除另一个项目时请求表中的项目,而读卡器将在多个位置查找该项目,则在读卡器搜索时,编写器可能会将该项目从未检查的位置移动到已检查过的位置,从而导致错误报告项目数据。OES不存在。
在.NET中,Dictionary<,> 和Hashtable 的区别主要在于前者是一个通用类型,因此您可以从静态类型检查(和简化装箱)方面获得通用类型的所有好处,但这并不像人们通常认为的性能那样大,尽管装箱有一定的内存成本。
人们说字典和哈希表是一样的。
这不一定是真的。哈希表是实现字典的一种方法。这是一个典型的例子,它可能是Dictionary 类中.net中的默认值,但它不是根据定义唯一的一个。
您同样可以使用链接列表或搜索树来实现一个字典,但它并没有那么有效(对于某些有效的度量标准而言)。
Docs女士说:"通过使用一个值的键来检索一个值是非常快的,接近于o(1),因为字典<(of<(tkey,tvalue>)>)类是作为一个哈希表来实现的。"—所以在处理Dictionary 时,应该保证有一个哈希表。但是,IDictionary 可以是任何东西。
@RIX0RRR-我想你倒过来了,字典使用的是哈希表,而不是哈希表使用的是字典。
@JosephHamilton-Rix0rr说得对:"哈希表是字典的实现。"他指的是"字典"的概念,而不是类(注意小写)。从概念上讲,哈希表实现了字典接口。在.NET中,字典使用哈希表来实现IDictionary。太乱了;
我是在.NET中讨论的,因为他在回答中引用了这个。
@JosephHamilton:实现(或实现)甚至与使用的含义都不同。恰恰相反。如果他说的稍微有点不同(但意思相同),也许会更清楚:"哈希表是实现字典的一种方法"。也就是说,如果您想要字典的功能,实现该功能的一种方法(实现字典)是使用哈希表。
@JosephHamilton"我在.NET中讨论过,因为他在回答中引用了这个。"——无论如何,你都错了,.NET字典类不使用或以任何其他方式引用.NET哈希表类(并且没有.NET哈希表类)。RIX0RRR的答案是完全正确的,而不是以任何方式向后。
@jimbalter.net hashtable->docs.microsoft.com/en-us/dotnet/api/&hellip;
@jimbalter"The dictionarygeneric class提供了从一组键到一组值的映射。字典中的每一项添加都包含一个值及其关联键。使用其键检索值非常快,接近于o(1),因为字典类是作为哈希表实现的。"docs.microsoft.com/en-us/dotnet/api/&hellip;
@约瑟夫汉密尔顿和这有什么关系?首先,"hashtable"!="哈希表"。第二,"哈希表"!=".NET哈希表类"。所有这些都在这里反复讨论…请仔细阅读。我不会对你的不准确作进一步的答复。
@Jimbalter Lol XD公司
Collections &;Generics 是有用的在处理组中的对象。NET中的所有对象的集合,是在IEnumerable 接口,进而有ArrayList(Index-Value)) &;HashTable(Key-Value) 。在.NET Framework 2.0,ArrayList &;Hashtable 被替换与List &;Dictionary 。现在,ArrayList &;Hashtable 是更多的用在当前的项目。
之间的差分来Hashtable &;Dictionary Dictionary 是通用的,在Hastable 是不通用的。我们可以添加到任何类型的对象,而Hashtable 查询,但我们需要它的铸造所需的类型。操作系统,它是不安全的类型。但到Dictionary declaring本身,而我们可以指定键和值的类型,因此,在铸造时是要检索。
让我们看一个例子:
哈希表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
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 ) ;
}
}
}
词典
1 2 3 4 5 6 7 8 9 10 11 12 13 14
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 ) ;
}
}
}
我们可以使用var.来代替显式地为keyValuePair指定数据类型,这样可以减少键入-foreach(dt中的var-kv)…这只是一个建议。
字典:
如果我们试图找到一个不存在的键,它将返回/引发异常。
它比哈希表快,因为没有装箱和拆箱。
只有公共静态成员是线程安全的。
字典是一个通用类型,这意味着我们可以将它与任何数据类型一起使用(创建时,必须同时为键和值指定数据类型)。
示例:Dictionary =
new Dictionary();
dictionary是hashtable的类型安全实现,Keys 和Values 是强类型的。
Hashtable:
"如果我们试图找到一个不存在的密钥,它会返回/抛出异常。"如果您使用Dictionary.TryGetValue 则不会。
使用关于msdn的C文章对数据结构进行的广泛检查表明,碰撞解决策略也存在差异:
hashtable类使用一种称为rehashing的技术。
Rehashing works as follows: there is a set of hash different functions,
H1 ... Hn , and when inserting or retrieving an item from the hash
table, initially the H1 hash function is used. If this leads to a
collision, H2 is tried instead, and onwards up to Hn if needed.
字典使用了一种称为链接的技术。
With rehashing, in the event of a collision the hash is recomputed, and the new slot corresponding to a hash is tried. With chaining, however, a secondary data structure is utilized to hold
any collisions. Specifically, each slot in the Dictionary has an array
of elements that map to that bucket. In the event of a collision, the
colliding element is prepended to the bucket's list.
NET框架3.5,因为这也将有一个HashSet 提供所有可能需要的,如果你只有Dictionary 键和值。
如果你使用的操作系统Dictionary 永远设置值到null 到simulate型安全哈希表应该考虑到你可能HashSet 开关。
Hashtable 是一种松散类型的数据结构,因此您可以向Hashtable 添加任何类型的键和值。Dictionary 类是类型安全的Hashtable 实现,键和值是强类型的。创建Dictionary 实例时,必须同时为键和值指定数据类型。
注意,msdn说:"dictionary<(of<(tkey,tvalue>)>)类被实现为哈希表",而不是"dictionary<(of<(tkey,tvalue>)>)类被实现为哈希表"。
字典不是作为哈希表实现的,但它是按照哈希表的概念实现的。由于使用了泛型,实现与hashtable类无关,尽管在内部,Microsoft可以使用相同的代码,并用tkey和tvalue替换object类型的符号。
在.NET 1.0中,不存在泛型;这是哈希表和ArrayList最初开始的地方。
你能修一下那个msdn的报价吗?有些东西缺失或错误;它不符合语法,有些不可理解。
HashTable:
键/值将在存储到堆中时转换为对象(装箱)类型。
从堆中读取时,需要将键/值转换为所需类型。
这些操作非常昂贵。我们需要尽可能避免装箱/拆箱。
字典:哈希表的通用变量。
禁止装箱/拆箱。不需要转换。
该桶是由哈希表对象包含的元素的集合。只要是一个水桶在哈希表中的虚拟元件,这使得更容易和更快的检索和检索比在大多数系列。
该词典具有相同功能的类的类的类。一本字典的特异型(有更好的表现比其他对象)是比哈希表哈希表元素的值类型是因为研究对象和类型,因此,装箱和拆箱typically发生如果储存或检索价值的类型。
进一步的阅读和词典:哈希表的集合类型
我能理解的另一个区别是:
我们不能在Web服务中使用字典。原因是没有Web服务标准支持泛型标准。
我们可以在基于SOAP的Web服务中使用通用列表(list)。但是,我们不能在Web服务中使用字典(或哈希表)。我认为原因是.NET XmlSerializer无法处理Dictionary对象。
Dictionary<> 是通用型操作系统和它的类型安全。
你可以插入任何类型的哈希表中的值,这可能会抛异常。但Dictionary 将只接受整数的值和Dictionary 同样将只接受字符串。
操作系统,它是更好的使用Hashtable Dictionary<> 代替。
另一个重要的区别是哈希表是线程安全的。hashtable具有内置的多个读卡器/单编写器(mr/sw)线程安全性,这意味着hashtable允许一个编写器与多个读卡器一起使用而不进行锁定。
对于字典,没有线程安全;如果需要线程安全,必须实现自己的同步。
进一步阐述:
Hashtable provides some thread-safety through the Synchronized property, which returns a thread-safe wrapper around the collection. The wrapper works by locking the entire collection on every add or remove operation. Therefore, each thread that is attempting to access the collection must wait for its turn to take the one lock. This is not scalable and can cause significant performance degradation for large collections. Also, the design is not completely protected from race conditions.
The .NET Framework 2.0 collection classes like List, Dictionary , etc. do not provide any thread synchronization; user code must provide all synchronization when items are added or removed on multiple threads concurrently
如果需要类型安全和线程安全,请使用.NET框架中的并发集合类。进一步阅读。
另外一个区别是,当我们在字典中添加多个条目时,条目的添加顺序是保持不变的。当我们从字典中检索条目时,我们将按照插入它们的相同顺序获取记录。而hashtable不保留插入顺序。
In most programming languages, dictionaries are preferred over hashtables
我不认为这是必然的,大多数语言都有一种或另一种,这取决于他们喜欢的术语。
然而,在C中,(对我来说)明显的原因是C哈希表和System.Collections命名空间的其他成员基本上已过时。它们出现在C v1.1中。它们已被System.Collections.Generic命名空间中的泛型类从C_2.0替换。
哈希表比字典的一个优点是,如果字典中不存在键,它将抛出一个错误。如果哈希表中不存在键,则返回空值。
在C中,我仍然避免使用System.Collections.Hashtable,因为它们没有泛型的优势。如果不知道密钥是否存在,可以使用字典的TryGetValue或HasKey。
哎呀,没有钥匙,应该有钥匙。
根据我使用.NET Reflector看到的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
[ 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在内部使用哈希表。
System.Collections.Generic.Dictionary不是从DictionaryBase派生的。
"所以我们可以确保DictionaryBase在内部使用哈希表。"——这很好,但它与问题无关。