java.lnag.Object中对hashCode的约定:
看个不改写hashCode导致使用hashMap不能出现预期结果的例子:
依照这个处方,得PhoneNumber的hashCode方法: public int hashCode(){ int result=17; result=37*result+areaCode; result=37*result+exchange; result=37*result+extension; return result; } 如果计算散列码的代价比较高,可以考虑用内部保存这个码,在创建是生成或迟缓初始化生成它。不要试图从散列码计算中排除掉一个对象的关键部分以提高性能。 style="MARGIN-TOP: 0px; FLOAT: left" border="0" marginwidth="0" framespacing="0" marginheight="0" src="http://wz.youkuaiyun.com/vote.aspx?t=equals%28%29%20%u548C%20hashCode%28%29%20-%20Yonghua%27s%20Tech%20Space%20-%20优快云Blog&u=http%3A//blog.youkuaiyun.com/dr2tr/archive/2007/02/28/1516722.aspx" frameborder="0" noresize="noresize" width="54" scrolling="no" height="75"> 我们知道,equals()函数是用来做比较的。java中的比较有两种:一种是内存地址的比较,一种是内容的比较。而比较个体也有两种:一种是简单类型(这类简单说来无所谓内存地址的比较或者内容比较的区别);还有一种是对象的比较,本文中说的主要是后者 在java中,(对象)内存地址的比较,是通过==完成的。比如 ![]() ![]() ![]() ![]() 这样的语句中,我们认为,如果obj1和obj2的内存地址相同,则返回true 而equals()通常是比较内容的。这里说“通常” ,是因为在最根本的Object类中,equal()函数做的是地址的比较。而在其他几乎所有的类中,equals()都经过重载,进行内容的比较。 而在说equals()的时候我们还涉及hashCode()是因为在有些应用中(比如,HashMap的key是对象),必须在重载equals()的同时重载hashCode()。因为java中默认(Object)的hashCode是根据对象的地址计算得到的。 我们通常不会注意到这个问题,因为我们通常所使用的key都是简单类型,或者是String, Long等一些特殊的对象(其特殊性请参看笔者在写java 浅拷贝和深拷贝时的讨论),这时候,这个问题被我们无意间绕过了 有人已经概括了这种我们忽略了的情况:“如果你想将一个对象A放入另一个收集(集合)对象B里,或者使用这个对象A为查找一个元对象在收集对 象B里位置的钥匙(key),并支持是否容纳(isContains()),删除收集对象B里的元对象(remove()?)这样的操作,那么,equals()和hashCode()函数必须开发者自己定义。” (括号为笔者添加) 为了便于理解,举一段程序为例: ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 这段代码的结果是什么?答案是nullPointerExcetpion. 而把hashCode()的注释去除,程序就可以返回正确的结果了。为什么呢?因为: Map.put(key,value)时根据key.hashCode生成一个内部hash值,根据这个hash值将对象存放在一个table中 Map.get(key)会比较key.hashCode和equals方法,当且仅当这两者相等时,才能正确定位到table。而我们说过,默认的java是对地址进行比较的。
参考: http://blog.youkuaiyun.com/RichardSundusky/archive/2007/02/12/1508028.aspx http://blog.youkuaiyun.com/pbnow/archive/2006/04/25/677253.aspx http://blog.youkuaiyun.com/jery_lee/archive/2004/10/13/135484.aspx http://blog.youkuaiyun.com/ngqzmjmj/archive/2005/04/27/365149.aspx Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=1516722 |
改写equals时总是要改写hashCode
最新推荐文章于 2025-08-08 22:01:10 发布