为什么覆写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

目录
相关文章
|
存储 算法 Java
(强制)要求覆写equals必须覆写hashCode(原理分析)
hashCode和equals hashCode和equals用来标识对象,两个方法协同工作可用来判断两个对象是否相等。众所周知,根据生成的哈希将数据散列开来,可以使存取元素更快。对象通过调用Object.hashCode()生成哈希值;由于不可避免会存在哈希值冲突 的情况,因此当hashCode相同时,还需要再调用equals进行一次值的比较;但是若hashCode不同,将直接判定Object不同,跳过equals,这加快了冲突处理效率。Object类定义中对hashCode和equals要求如下:
260 0
|
存储 Java
为什么重写equals必须重写hashCode
面试中高频的问题,从根本理解重写equals为什么要重写hashCode,以及不重写会带来哪些问题。
|
10月前
|
存储 Java
为什么要重写hashCode()和equals()(深入了解)
为什么要重写hashCode()和equals()(深入了解)
|
10月前
|
存储 算法 Java
为什么要重写 hashcode 和 equals 方法
为什么要重写 hashcode 和 equals 方法
69 0
|
Java 程序员 关系型数据库
重写hashCode()和equals()方法
hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它为我们的编程提供便利的同时也带来了很多危险.这篇文章我们就讨论一下如何正解理解和使用这2个方法. 如何重写equals方法 如何重写hashCode方法 重写equals而不重写hashCode的风险 如何重写equals()方法 如果你决定要重写equals()
2926 1
为什么要重写 hashcode 和 equals 方法?
为什么要重写 hashcode 和 equals 方法?
121 0
|
存储
重写equals后为什么要重写hashcode方法
重写equals后为什么要重写hashcode方法
80 0
|
10月前
|
存储 IDE Java
为什么重写 equals() 时必须重写 hashCode() 方法?(简单易理解)
为什么重写 equals() 时必须重写 hashCode() 方法?(简单易理解)
74 1
|
Java 程序员 容器
如何正确的重写hashcode()
如何正确的重写hashcode()
1724 0
如何正确的重写hashcode()