2

谁能帮我理解 GetHashCode() 方法如何处理字符串值?

MSDN我发现:

如果两个字符串对象相等,则 GetHashCode 方法返回相同的值。但是,每个唯一的字符串值都没有唯一的哈希码值。不同的字符串可以返回相同的哈希码。

所以,不同的字符串可以返回相同的哈希码,哈希码对于字符串来说不是唯一的。它会导致程序核心出现错误吗?

4

5 回答 5

3

如果您假设匹配的哈希码意味着匹配的字符串,则可能会导致错误。通常,您使用哈希码将字符串分类到存储桶中,以便快速搜索和选择。如果您检测到两个字符串具有匹配的哈希码,那么您通常会比较字符串本身是否相等。

如果这不能回答你的问题,那么我不明白这个问题。

于 2012-09-17T18:23:52.657 回答
3

好吧,如果您的算法依赖于每个字符串具有唯一的哈希值,这可能会导致错误。

例如,哈希映射(.NET 中的字典)可能会因冲突而失败(即具有相同哈希但不相等的两个对象),或者它在处理冲突时不会失败,这取决于确切的实现。在这种情况下失败意味着:如果您向映射添加一个新对象,并且映射中已经有一个对象与新对象具有相同的哈希值,那么新对象将覆盖旧对象,而不是仅仅被添加。据我所知,.NET 中的 Dictionary 类可以处理冲突。

如果您需要更具体的建议,您需要提出一个更具体的问题:您要存档什么,您打算如何存档等。

作为旁注:字符串的哈希值通常不是唯一的,因为哈希值的大小是有限的,而字符串的长度不是。可以这样想:假设哈希函数是 MD5(它不是 .Net 中的默认值),并且您有一个字符串都由十六进制字符(0-9A-Z)组成,并且字符串长度为 200 个字符:有字符串有 200^16 个可能的值,但其哈希值只有 32^16 个可能的值。

于 2012-09-17T18:24:35.890 回答
2

所以,不同的字符串可以返回相同的哈希码,哈希码对于字符串来说不是唯一的。它会导致程序核心出现错误吗?

如果哈希值按预期使用,它不应该导致错误。返回的GetHashCode()哈希并不是为了提供唯一的哈希——这是不可能的,因为只有大约 40 亿个可能的哈希码(因为该方法返回一个Int32),但可能的字符串数量是无限的。

哈希旨在提供很少的集合,而不是没有冲突。因此,您永远不应假设哈希是基于值的唯一表示。您得到的唯一保证是两个不同字符串的两个不同哈希码意味着字符串不相等,因为两个相等的值应该始终产生相同的哈希。然而,两个相等的哈希码并不一定意味着两个字符串值相等。

于 2012-09-17T18:28:51.323 回答
2

Hashcode 用于加快在 Hash 集合中搜索对象的速度。在内部,它们将对象存储在许多桶中。持有的对象根据其哈希码分为桶。因此,例如,当您打电话时

var value = Dictionary["someKey"]

字典而不是在所有内部存储桶中搜索,而是直接转到应该在该键下包含值的存储桶。字典搜索只在那个桶里。

也许这不完全是它的实现方式,但它或多或少应该是它。所以在这种情况下,字典中的不同键具有相同的哈希码并不重要。这仅意味着该键下的值将最终在同一个存储桶中。

于 2012-09-17T18:29:17.317 回答
2

实际上,该文档对方法所做的保证非常准确。哈希码只是遵循以下两条规则(为便于阅读,a == b参考a.Equals(b)#a参考):a.GetHashCode()

  • 如果a == b那么#a == #b
  • 如果#a != #b那么a != b

请注意,这不是Equals和匹配哈希之间的等价。如果您依赖的不止于此,那么您的代码显然有错误。GetHashCode旨在将对象用作字典中的键,以便从对象快速映射到数字,但它不需要是可逆的。如果您查看字符串,您可以很容易地看到可能的字符串数量很快超过了可能的哈希码数量,因此您可以自己回答这个问题。您已经超过了 2 32 个可能的字符串,并且已经超过了两个字符。

于 2012-09-17T18:31:13.947 回答