为什么重写equals方法的同时也要重写hashcode方法

为什么重写equals方法的同时也要重写hashcode方法

注:JDK版本:1.8.0_251

首先,我们来看一下在Object类中,这两个方法是是干嘛的,现贴出代码:
为什么重写equals方法的同时也要重写hashcode方法

在Object类中, equals方法进行相等比较,是用 == 号对两个对象进行比较。我们知道,在Java中,==比较,如果不是基本数据类型的话,那么实际比较的是对象在内存中的地址。
  
我们再看看Object类的hashCode()方法:
为什么重写equals方法的同时也要重写hashcode方法
这个方法呢,它是一个native方法,这个方法会返回当前对象的哈希散列码。

OK,现在打完了Object类的铺垫,我们再来看看HashMap的containsKey()方法的源码:
为什么重写equals方法的同时也要重写hashcode方法
为什么重写equals方法的同时也要重写hashcode方法

这个hash方法,是HashMap用来定位key所命中的bucket的位置。

比如说,我们定义如下一个User类:
为什么重写equals方法的同时也要重写hashcode方法

现在我们来创建两个User对象,这两个User对象的每一个字段都完全一样,我们要把User对象当作HashMap中的key进行存储的话,那么我们看看它们的hashCode()方法的执行结果是否一样?
为什么重写equals方法的同时也要重写hashcode方法

显然,它们的hashCode是不一样的,接下来,那么将该对应作为HashMap的key,就会有问题了。因为我们希望这两个对象命中同一个bucket,但事实上,这两个对象因为hashcode的不一样,而会命中不一样的bucket。我们现在覆盖一下User类的equals方法和hashCode方法:
为什么重写equals方法的同时也要重写hashcode方法

覆盖了这两个方法之后,我们再执行上面的test代码,我们再看看效果:
为什么重写equals方法的同时也要重写hashcode方法

这个时候,他们的hascode也是一样的了。

那有的人可能会说了,那我只覆盖hashcode方法,不覆盖equals方法,它不行吗???好吧,那我们来看看HashMap的containsValue()方法的代码:
为什么重写equals方法的同时也要重写hashcode方法

前端我们提及过,containsValue方法调用的是Object.equals()方法,如果我们不去覆盖它的话,它只会拿对象的地址进行比较,像上面User类这样的需求,所有字段值完全相同的User对象,也就断然不可能相等了。。。

因此,我们在对一个类的equals方法进行覆盖的时候,通常情况下,我们会同时覆盖equals方法和hashCode()方法。