为什么覆写equals的时候一定要覆写hashCode?

简介: 为啥很多地方说“覆写equals的时候一定要覆写hashCode”。说到这里我知道很多人知道有个原则:如果a.equals(b)那么要确保a.hashCode()==b.hashCode()。为什么?hashCode和我写的程序的业务逻辑毫无关系,为啥我要override? 要我说如果你的class永远不可能放在hash code为基础的容器内,不必劳神,您真的不必override hashCode() :)     说得准确一点放在HashMap和Hashtable里面如果是作为value而不是作为key的话也是不必override hashCode了。

  为啥很多地方说“覆写equals的时候一定要覆写hashCode”。说到这里我知道很多人知道有个原则:如果a.equals(b)那么要确保a.hashCode()==b.hashCode()。为什么?hashCode和我写的程序的业务逻辑毫无关系,为啥我要override? 要我说如果你的class永远不可能放在hash code为基础的容器内,不必劳神,您真的不必override hashCode() :)

    说得准确一点放在HashMap和Hashtable里面如果是作为value而不是作为key的话也是不必override hashCode了。至于HashSet,实际上它只是忽略value的HashMap,每次HashSet.add(o)其实就是HashMap.put(o, dummyObject)。

    那为什么放到Hash容器里面要overide hashCode呢?因为每次get的时候HashMap既要看equals是不是true也要看hash code是不是一致,put的时候也是要看equals和hash code。

    如果说到这里您还是不太明白,咱就举个例子:

    譬如把一个自己定义的class Foo{...}作为key放到HashMap。实际上HashMap也是把数据存在一个数组里面,所以在put函数里面,HashMap会调Foo.hashCode()算出作为这个元素在数组里面的下标,然后把key和value封装成一个对象放到数组。等一下,万一2个对象算出来的hash code一样怎么办?会不会冲掉?先回答第2个问题,会不会冲掉就要看Foo.equals()了,如果equals()也是true那就要冲掉了。万一是false,就是所谓的collision了。当2个元素hashCode一样但是equals为false的时候,那个HashMap里面的数组的这个元素就变成了链表。也就是hash code一样的元素在一个链表里面,链表的头在那个数组里面。

回过来说get的时候,HashMap也先调key.hashCode()算出数组下标,然后看equals如果是true就是找到了,所以就涉及了equals。

    假设如果有个key为a的元素在HashMap里面的情况:

    1:如果这时候用equals为true但是hashCode不等的b作为get参数的话,这个时候b算出来的数组下标一定不是a所在的下标位置。

    2:如果这时候用equals为false但是hashCode相等的b作为get参数的话,这个时候b算出来的数组下标是对了,但是用equals来寻找相符的key就找不到a了。

    以上2种情况要么就是get找不到符合的元素返回null,要么就是返回一个hashCode和equals恰好都符合b的另外的元素,这就产生了混乱。混乱的根本就是错误实现hashCode和equals。

Mark:可以参考Bloch的<Effective Java>的 Item 9: Always override hashCode when you override equals

目录
相关文章
|
28天前
|
存储 算法 Java
为什么要重写 hashcode 和 equals 方法
为什么要重写 hashcode 和 equals 方法
22 0
|
4月前
|
存储
重写equals后为什么要重写hashcode方法
重写equals后为什么要重写hashcode方法
44 0
|
1月前
|
存储 Java
为什么要重写hashCode()和equals()(深入了解)
为什么要重写hashCode()和equals()(深入了解)
|
1月前
|
自然语言处理 算法 Java
为什么说重写equals时要重写hashcode
为什么说重写equals时要重写hashcode
|
3月前
|
存储 IDE Java
为什么重写 equals() 时必须重写 hashCode() 方法?(简单易理解)
为什么重写 equals() 时必须重写 hashCode() 方法?(简单易理解)
17 1
|
8月前
|
存储
为什么重写 equals 方法就必须重写 hashCode 方法?
为什么重写 equals 方法就必须重写 hashCode 方法?
60 0
|
9月前
|
存储 Java
重写equals方法
我们在java程序中调用自带的equals方法时,你是否会有这样的疑问:明明我比较的数据都一样啊,为什么会返回false呢?有些人可能还会疑问,怎么有时候返回true?有时候返回false呢?这是为什么呢?其实是和Java底层人家写的equals方法逻辑有关系
|
9月前
为什么要重写 hashcode 和 equals 方法?
为什么要重写 hashcode 和 equals 方法?
54 0
|
存储 算法 Java
(强制)要求覆写equals必须覆写hashCode(原理分析)
hashCode和equals hashCode和equals用来标识对象,两个方法协同工作可用来判断两个对象是否相等。众所周知,根据生成的哈希将数据散列开来,可以使存取元素更快。对象通过调用Object.hashCode()生成哈希值;由于不可避免会存在哈希值冲突 的情况,因此当hashCode相同时,还需要再调用equals进行一次值的比较;但是若hashCode不同,将直接判定Object不同,跳过equals,这加快了冲突处理效率。Object类定义中对hashCode和equals要求如下:
192 0
|
存储 Java 对象存储
JavaSE——为什么重写equals的同时一定要重写hashCode?
JavaSE——为什么重写equals的同时一定要重写hashCode?
JavaSE——为什么重写equals的同时一定要重写hashCode?