C#中有关string.GetHashCode()的一个重要注意事项!
来源:互联网 发布:js apply的z作用 编辑:程序博客网 时间:2024/05/19 22:58
最近在做项目的时候,需要把字符串存入数据库,并且要求数据库中不能有重复的字符串,由此就引出了将字符串hash成特定的hash值,依靠查询hash值是否重复来判断字符串是否重复。
这样做的好处在于查询重复字符串的代价太大,因为字符串可能会非常长,进行逐个比较非常消耗数据库的性能,如果将字符串hash之后,依靠hash值来查重就显得轻便很多了,因为hash值通常都比字符串本身短很多。
由于使用的是C#,自然而然就用了string的GetHashCode函数,MSDN上说该函数得到的返回值可以唯一区别一个string,意思就是相同的字符串肯定会得到相同的hash值,不同的字符串的hash值肯定不一样。当时还在疑惑,这个函数的返回值是int型,算起来也就几十亿,但是字符串的组合却是无穷的啊,微软是怎么实现唯一性的呢?
由于项目紧,也没多想,就先用着了。
结果今天以调试代码,发现用hash值查询一个数据库中已经存在的string,居然说没有重复!这就相当让人费解了,string已经存在了,那么其hash值也肯定已经存在在数据库中,怎么会说没有重复呢?仔细debug代码,惊讶的发现原来string的hash值居然变了,变成了一个和数据库中完全不同的值,怪不得说没有重复……
那么为什么同一个string,两次运行GetHashCode得到的返回值却不一样呢?
再次研究了这个“诡异”的函数。
原来GetHashCode只是保证在同一个进程的内存空间中,string的返回值可以唯一区别一个string,什么意思呢?就是在同一个进程的内存空间中,每个string的hash值都被微软保证不会重复(除非两个string的内容一样),虽然字符串的组合是无限的,但是对于一个进程的内存空间,顶多就几个G的,几个G的内存所能容纳的string的组合就变成了“有限的”了,int型的几十亿足够来保证这些“有限的”string组合有不同的hash值!
但是微软不保证同一个string在调用GetHashCode之后得到的返回值是相同的!因为int就几十亿,如果用来保证每次调用得到的返回值相同,那么势必出现hash值的碰撞!
这也是为什么MD5,SHA2等hash算法得到的返回值都是128位或者256位的原因,因为只有足够长,才能保证少发生碰撞或者发生碰撞之后可以二次hash!
PS:看看微软对这个函数的备注
http://msdn.microsoft.com/zh-cn/library/system.string.gethashcode.aspx
GetHashCode 的行为取决于它的实现,此实现可能会从一个公共语言运行时版本更改为另一个版本。 原因可能是为了提高 GetHashCode 的性能。
如果两个字符串对象相等,则 GetHashCode 方法返回相同的值。 但是,每个唯一的字符串值并没有唯一的哈希代码值。 不同的字符串可以返回相同的哈希代码。
有关哈希代码的更多信息,请参见 Object.GetHashCode。
- C#中有关string.GetHashCode()的一个重要注意事项!
- C#中有关string.GetHashCode()的一个重要注意事项!
- c#中关于gethashcode()的一点看法
- C# GetHashCode 的实现方式
- C#中有关string和byte[]转换的问题
- 转:C#中有关string和byte[]转换的问题
- C#中有关string和byte[]转换的问题
- C#中有关string和byte[]转换的问题
- C#中有关string和byte[]转换的问题
- C#中有关string和byte[]转换的问题
- C#中有关string和byte[]转换的问题
- c#中string类型的一个实验
- C# Dictionary中做Key的类应该注意重写getHashCode和Equals
- C# Dictionary中做Key的类应该注意重写getHashCode和Equals
- Java中使用JSON进行parse操作时一个重要的注意事项
- .NET中基本数据类型的GetHashCode
- 在C#中使用RegularExpressionValidator控件的一个注意事项
- Notes中有关C++API的注意事项
- [Django1.5]two-scoops-django-best-practics 笔记四
- CSS渲染原理
- 数据库用控制器导入sql
- 黑马程序员_集合1(ArrayList,LinkedList,Vector,Iterator,ListIterator)
- 水晶报表
- C#中有关string.GetHashCode()的一个重要注意事项!
- 第十一周项目二一——派生类的应用2(派生类不可直接调用基类)
- su与sudo的区别
- VI使用技巧总结
- JNDI (Java Naming and Directory Interface)
- POJ 1088 滑雪(DP+记忆化搜索)
- Sitemesh 自定义decorators.xml 文件路径
- office word 每页头上的这个字怎么删除不掉.?怎么更改里面的字!
- Java OutOfMemory Error引发的JVM参数实测--线程堆栈参数篇