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

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

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

所以我想知道, GetHashCode()总是生成一个不同的数字,即使我有很长的字符串或只有这个不同:’ä’而不是’a’

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

而且因为当你没有准备好时(客户端正在查看错误搜索的缓存结果),它会突然出现,我想确定…

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

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

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

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

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

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

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

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

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

逻辑上GetHashCode 不能是唯一的,因为只有2 ^ 32个int和无限数量的字符串(参见鸽子孔原理)。


正如@Henk在评论中指出的那样,即使存在无限数量的字符串,也存在有限数量的System.String 。 然而,鸽子洞原则仍然存在,因为后者比int.MaxValue

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

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

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

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

阅读Eric Lippert的这些guidlelines以正确使用GetHashCode ,他们非常指示。

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