有面试官会问:你重写过 hashcode和equals 么,为什么重写equals时必须重写hashCode方法?
equals和hashCode都是Object对象中的非final方法,它们设计的目的就是被用来覆盖(override)的,所以在程序设计中还是经常需要处理这两个方法.下面我们一起来看一下,它们到底有什么区别,总结一波!
hashCode介绍
hashCode()的作用是获取哈希码,也称为散列码,它实际上是返回一个int整数,这个哈希码的作用是确定该对象在哈希表中的索引位置,hashCode()定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode() 函数.
equals介绍
equals()它的作用也是判断两个对象是否相等,
如果对象重写了equals()方法,一般比较两个对象的内容是否相等,
如果没有重写,比较两个对象的地址是否相同,价于“==”,
同样的,equals()定义在JDK的Object.java中,这就意味着Java中的任何类都包含有equals()函数.
hashCode() 和 equals() 有什么关系?
如果该类不会在HashSet、 HashTable、 HashMap等这些本质是散列表的数据结构中用到,则hashCode()和equals()两者之间是没有关系的。
下面我们分析一下该类会在HashSet、 HashTable、 HashMap等这些本质是散列表的数据结构中用到时的关系:
equals相等的两个对象的hashcode一定相等;
equals不相等的两个对象的hashcode有可能相等.
示例代码
运行结果
######test2######
a.hashCode:1163157884
b.hashCode:1956725890
[Model{name='猿小豪', age='20'}, Model{name='猿小豪', age='20'}]
结果分析
我们重写了Model的equals(),但是很奇怪的发现HashSet中仍然有重复元素:a和b.
为什么会出现这种情况呢?
这是因为虽然a和b的内容相等,但是它们的hashCode()不等,所以HashSet在添加a和b的时候,认为它们不相等.
HashSet的add方法源码分析
HashSet中的add方法实际调用的是HashMap中的put方法,而HashMap的put方法中,使用key作为参数,在hash方法中用key的hashCode()计算出hash值,然后在putVal方法中使用计算出的hash值进行比较,如果hash值相同,再通过equals()比较key值是否相同,如果都相同,则覆盖原有的Node对象,否则创建新的Node对象放入链表中.
总结
如果类使用在散列表的集合对象中,要判断两个对象是否相同,除了要重写equals()之外,也要按照规则重写hashCode()函数,否则会出现”equals相等的两个对象的hashcode不相等”的情况,从而在使用相关集合时,引起与自己的预期不相符的情况.
补充
至于为什么先使用hash值判断再使用equals.
个人理解:
在计算存放数组下标的过程中,hash值已经通过hashCode计算得到了,后面就可以直接拿来用了,这样就减少了equals次数,提高了效率.