由于若是只覆盖了equals而没有覆盖hashCode, 则两个不一样的instance a和b虽然equals结果(业务逻辑上)相等,但却会有不一样的hashcode,这样hashmap里面会同时存在a和b,而实际上咱们须要hashmap里面只能保存其中一个,由于从业务逻辑方向看它们是相等的.
为了能让集合框架中的类如HashMap正常工做,必须保证同时覆盖equals()和hashCode(),并且注意不要因为写错了参数类型,而重载了这两个方法,却并无覆盖它们,好比:
public boolean equals(Object obj) 写成了public boolean equals(ClassXXX obj) 。
为何在覆盖equals时必定也要覆盖hashCode呢? 下面用HashMap来阐述缘由,首先假设key1和key2的值在业务逻辑领域是相等的,即它们应该是同一个对象,HashMap已经存储了key1,如今要查找key2是否存在,正确的结果应该是存在:
Java中的HashMap其实是一个链表数组,即首先HashMap是一个数组,而后数组中的每个元素是一个链表(更通用的概念能够称为桶bucket,Java中的HashMap用Entry类描述链表的结点结构),HashMap在执行Put,Contains之类的操做时,会首先根据你提供的Key计算hashCode值,而后根据这个hashCode值在数组中找到某一个链表或桶(一般是找到链表的起始结点),这一步操做利用了hashCode()方法,若是你覆盖了就会用你提供的方法,在找到某一个链表的起始结点后,就会遍历链表,而后经过equals方法来寻找是否存在与Key的值相等的结点,若是执行equals方法后的结果相等,HashMap就认为已经存在这个元素,这一步若是你覆盖了equals方法就会用到你提供的equals方法。
经过上面的描述,咱们发现equals方法和hashCode方法若是不一样时按你本身逻辑覆盖的话,HashMap就会出问题。好比你只覆盖了equals方法而没有覆盖hashCode方法,那么HashMap在第一步寻找链表的时候会出错,有一样值的两个对象Key1和Key2并不会指向同一个链表或桶,由于你没有提供本身的hashCode方法,那么就会使用Object的hashCode方法,该方法是根据内存地址来比较两个对象是否一致,因为Key1和Key2有不桶的内存地址,因此会指向不一样的链表,这样HashMap会认为key2不存在,虽然咱们指望Key1和Key2是同一个对象;反之若是只覆盖了hashCode方法而没有覆盖equals方法,那么虽然第一步操做会使Key1和Key2找到同一个链表,可是因为equals没有覆盖,那么在遍历链表的元素时,key1.equals(key2)也会失败(事实上Object的equals方法也是比较内存地址),从而HashMap认为不存在Key2对象,这一样也是不正确的。
如下内容摘自<<Effective Java>>
覆盖equals时总要覆盖hashCode,一个很常见的错误根源在没有覆盖hashCode方法。在每一个覆盖了equals方法的类中,也必须覆盖hashCode方法。若是不这样作的话,就会违反Object.hashCode的通用约定,从而致使该类没法结合全部基于散列的集合一块儿正常工做,这样的集合包括HashMap、HashSet和Hashtable。
下面是约定的内容,摘自Object规范[JavaSE6]:
1)在应用程序的执行期间,只要对象的equals方法所用到的信息没有被修改,那么对这同一个对象调用屡次,hashCode方法都必须始终如一地返回同一个整数。在同一个应用程序的屡次执行过程当中,每次执行所返回的整数能够不一致。
2)若是两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生一样的整数结果。
3)若是两个对象根据equals(Object)方法比较是不相等的,那么调用这两个对象中的任意一个对象的hashCode方法,则不必定要产生不一样的整数结果。可是程序员应该知道,给不相同的对象产生大相径庭的整数结果,有可能提供散列表(hash table)的性能。
若是覆盖equals没有覆盖hashCode,将会违反上面的第2条:相等的对象必须具备相等的散列码(hashCode)。Object类里面的默认eqals方法是比较内存地址是否相等,默认的hashCode方法则是根据内存地址产生一个整数,因此Object类自己固然是符合上面规则的。当你覆盖了equals后,内存地址不一样的对象可能会相等,而若是这时你没有覆盖hashCode方法的话,hashCode仍是根据内存地址来生成,就会出现相等的对象具备不一样的散列码的状况。程序员