字典中的条目是否有限制<>?

时间:2010-08-11 16:46:05

标签: c# silverlight performance dictionary idictionary

我需要整理大约3000个不同的文件,并在游戏过程中的不同时间检索。

我创建了自己的变量结构。 我在考虑创建一个“词典” 在我的应用程序开始时,只需在游戏开始前加载我的所有文件。

我想知道性能:有这么多条目的字典会导致我的应用程序变慢吗? 大字典是否会使“TryGetValue”和“ContainsKey”运行得更慢?

感谢您的建议!

8 个答案:

答案 0 :(得分:14)

TryGetValue和ContainsKey在这个大小上应该非常快,只要密钥具有良好分布的哈希值。

字典具有可索引的“桶”数。当它通过键添加或查找值时,它将获取GetHashCode()返回的值,再次将其向下散列为小于桶的数量(通常像模数一样简单,但实现未定义),并查看相关的桶。

该桶目前将有零个或多个项目。字典将使用.Equals()将每个项目与密钥进行比较。

找到正确的桶的第一位将是恒定时间O(1)。将密钥与桶中的密钥进行比较的第二位将是在线性时间O(n),其中n仅涉及该桶中的项目数,而不是整个集合中的项目数。

通常每个桶中的项目应该非常少(桶的数量会增加以试图保持这种情况)所以操作基本上是恒定的时间。

但是,如果您的哈希码执行得不好,那么同一个桶中会有很多键。时间复杂度将越来越接近O(n),可以通过试验具有故意错误的GetHashCode的对象来看到,每次只返回0。在更糟糕的情况下,它比List更糟糕,因为List也是O(n),但是Dictionary有更多的开销。

这是否意味着你应该担心?不,即使是相对天真的散列方法也应该给出相对好的结果。如果你正在使用字符串键,那么它可能已经足够好了。如果你使用的是简单的内置类型,那就更好了。

如果您确实发现访问字典的速度很慢,那么您需要注意这一点并修复GetHashCode()方法或创建IEqualityComparer(它允许您为GetHashCode()和Equals()定义外部规则用于字典,哈希集等)。

最有可能的是,3000不算什么,它会没事的。

答案 1 :(得分:12)

Dictionary<>正在填充3000个条目。这不会成为经济放缓的源头。

启动时将3000个不同的文件读入内存,另一方面,变慢。只有在需要时才将文件读入内存会更好,但之后将它们保存在内存中以便后续访问。

答案 2 :(得分:7)

不,不会。它将消耗内存,但TryGetValueContainKey应该非常快,因为字典是一个哈希表,并且通过键访问元素是不变的,它不依赖于元素的数量。

答案 3 :(得分:4)

为字典键类型提供哈希码算法在Int32空间中相对均匀地分布哈希码,哈希码查找不受字典大小的影响。

有关详细信息,请参阅http://en.wikipedia.org/wiki/Hashtable#Performance_analysis

答案 4 :(得分:3)

有一个限制,但3000不远。 Dictionary<>使用Object.GetHashCode()对其密钥进行oraginise,后者返回int。因此,在发生冲突之前,您最多可以存储2^32(4,294,967,296)个键。但是,由于.Net的哈希码通常会被计算出来,因此当你接近这个神奇的数字时,可能会发生很多冲突。

添加更多密钥不会减慢TryGetValueContainsKey的速度 - 它们是O(1)次操作。

答案 5 :(得分:1)

.NET中的字典使用哈希表查找方案,因此添加条目对查找性能的影响很小(如果有的话)。您将遇到的唯一问题可能是内存使用情况。包含3000个项目的字典将占用密钥使用的存储量的大约3000倍以及值类型。如果它只是一个没有巨大二进制blob的简单结构,那么3000就非常小了。

答案 6 :(得分:1)

你的瓶颈不是字典的表现,而是读取3000个文件。

答案 7 :(得分:1)

与大多数计算机一样(特别是性能),“它取决于(tm)”

这完全取决于Dictionary的实现。

它可以作为二叉树来完成,在这种情况下,查找应该是O(log2 N),这意味着查找时间随着字典大小的增长而缓慢增长。

它可以作为哈希表来完成,理论上它是O(1),这意味着无论字典的大小如何,查找总是会花费相同的时间,但这就是理论,并且依赖于关于桶的数量和哈希码的质量。许多项目最终都在同一个桶中,需要线性搜索,随着字典的增长,事情会大大减慢。

然而,在看到明显的差异之前,字典必须增加到数量级超过3000。