我可以使用GetHashCode()进行所有字符串比较吗?

时间:2012-09-11 09:38:33

标签: c# hashcode

我想基于要搜索的对象和一些搜索设置来缓存一些搜索结果。

但是:这会创建相当长的缓存键,我想我会为它创建一个快捷方式,我想我会使用GetHashCode()

所以我想知道,GetHashCode()总是产生一个不同的数字,即使我有很长的字符串或仅仅因此而有所不同:'ä'而不是'a'

我尝试了一些字符串并且似乎答案是肯定的,但不理解GetHashCode()行为并不能给我真实的感觉。

因为当你没有准备好时(客户端正在查看错误搜索的缓存结果),它会突然显示出来之一,我想确定...

编辑:如果MD5可以工作,我可以改变我的代码而不是使用GetHashCode ofcourse,目标是得到一个比原来的短(呃)字符串(> 1000个字符)

5 个答案:

答案 0 :(得分:8)

您不能指望GetHashCode()是唯一的。

有一篇很好的文章调查http://kenneththorman.blogspot.com/2010/09/c-net-equals-and-gethashcode.html可能发生碰撞的可能性。结果是“GetHashCode()调用不同字符串返回相同哈希码的最小次数是在565次迭代之后,获得哈希码冲突之前的最大迭代次数是296390次迭代。”

为了使您能够理解GetHashCode实现的合同,以下是Object.GetHashCode()的MSDN文档的摘录:

哈希函数必须具有以下属性:

  • 如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值。但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值。

  • 对象的GetHashCode方法必须始终返回相同的哈希码,只要对对象状态没有修改即可确定对象的Equals方法的返回值。请注意,这仅适用于当前应用程序的执行,并且如果再次运行应用程序,则可以返回不同的哈希代码。

  • 为获得最佳性能,哈希函数必须为所有输入生成随机分布。

C#编译器团队的Eric Lippert在http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/的博客上解释了GetHashCode实施规则的基本原理。

答案 1 :(得分:8)

逻辑上GetHashCode 不能唯一,因为只有2 ^ 32个整数和无限数量的字符串(请参阅pigeon hole原则)。


正如@Henk在评论中指出的那样,即使有无数个字符串,也有finite number of System.Strings。然而,鸽子洞原则仍然存在,因为后者比int.MaxValue大得多。

答案 2 :(得分:2)

如果有人将每个字符串的哈希码与字符串本身一起存储,则可以将字符串的哈希码作为“第一步”来比较它们的相等性。如果两个字符串具有不同的哈希码,则它们不相等,并且不需要做任何其他事情。如果希望比较具有相同长度且“几乎”但不完全相等的许多字符串对,则在检查内容之前检查哈希码可能是有用的性能优化。 请注意,如果没有缓存的哈希码,这种“优化”是不值得的,因为计算两个字符串的哈希码几乎肯定比比较它们慢。但是,如果为了其他目的而必须计算和缓存哈希码,那么检查哈希码作为比较字符串的第一步可能很有用。

答案 3 :(得分:1)

使用GetHashCode()时总是冒着冲突的风险,因为你在有限数量的空间Int32中运行,而且哈希算法在这个空间内不能完美分布的事实也会加剧这种情况。

如果查看HashTable或Dictionary的实现,您将看到GetHashCode用于将密钥分配到存储桶中以减少所需的比较次数,但是,如果有多个项目,则仍需要进行相等比较。同一桶。

答案 4 :(得分:0)

没有。 GetHasCode只提供哈希码。会有碰撞。具有不同的散列意味着字符串不同,但具有相同的散列并不意味着字符串是相同的。

阅读these guidlelines by Eric Lippert for correct use of GetHashCode,他们非常指示。

如果你想比较字符串,就这样做吧! stringA == stringB工作正常。 如果要确保字符串在大型集合中是唯一的,请使用哈希代码的强大功能,使用HashSet<string>