为什么重写equals方法之后必须要重写hashCode
目录一. 结论二. 为什么要重写 equals 方法三. 重写 equals 但不重写 hashCode 会出现什么问题四. 什么是散列表五. 总结概括一. 结论1重写 equals 不重写 hashCode 运行时并不会报错但是在逻辑上会报错2并不是每次重写 equals 都必须重写 hashCode但推荐都写上去二. 为什么要重写 equals 方法原因很简单默认的 equals 方法无法满足我们的正常开发需求我们需要对它进行重写升级。我们先来看一下所有类的祖宗 Object 类中 equals 方法的代码这可以让我们理解为什么要重写equals。可以看出在 Object 类的源码中它的 equals 方法就是很简单的用了 来判断了一下。众所周知 是对类对象的引用做判断判断引用是否相等。所以默认的 equals 的逻辑就是判断的双方是否引用了一个对象如果是那就是相等的如果不是那就不相等。默认的 equals 看似能满足我们的要求但有些情况下却不能。在开发过程中我们更希望比较的是两个对象的内容是否相等。比如两个字符串String a 123456String b 123456内容完全一样在我们看来这两个字符串就是相等的。但在 equals 方法看来两个字符串的内存地址不相等所以仍然会判定为不相等这就与我们期望的判断结果发生了矛盾所以需要去重写 equals 方法只有重写了equals 方法之后我们再去判断 a 和 b此时判断结果就会相等。三. 重写 equals 但不重写 hashCode 会出现什么问题我们来看下面这段代码public class EqualsAndHashcode { public static void main(String[] args) { people people1 new people(); people people new people(); System.out.println(people.equals(people1)); } } class people{ private String name; private int age; public people(){ name 李华; age 18; } Override public boolean equals(Object obj) { if(this obj){ return true; } if (objnull){ return false; } if(getClass() ! obj.getClass()){ return false; } people other (people) obj; return Objects.equals(name,other.name) age other.age; } }可以看出对于两个具有初始化 people 对象equals 是可以满足我们的要求的。上面的代码看似没有问题达到了我们想要的结果但这只是因为我们还没有遇到是它犯错的情况散列表。四. 什么是散列表先介绍一下散列表的工作原理简单来说就好比是一个货物架货物架上的每个位置只能放一个商品我们拿到一个货物之后需要先找到这个货物对应应该存放的位置然后就把它放到对应的位置。hashCode 就是这样它会先计算对象的哈希值 然后通过哈希值找到它该存放的位置如果这个位置是空的就直接放上去如果这个地方已经放有货物了就用 equals 比较一下要放置的货物和当前已经存放的货物是不是同一个如果是同一个就不放了不是的话就会把它放在另一个位置。为什么遇到散列表上面的代码就会出错呢原因就是哈希函数既然我们想让两个属性一样的类对象是为相等那么在散列表中也应当如此。如下代码照这么看来上面的代码还能满足我们的要求吗很明显set 里面有两个元素虽然我们认为这两个元素是一样的可 set 不这么认为。这样显然不是我们想要的结果他俩明明就相同为什么还要加进去呢到这这个结果的罪魁祸首相比大家都知道了吧就是因为哈希函数。我们先来看看 Object 中的 hashCode 是怎么样的我们再来打印一下这两个people对象的hashCode来看一下从结果就可以看出来这两个 people 是不一样的所以把他们两个都放进去也就合情合理了。到这里我们就知道问题的原因了重写 hashCode 的可以保证我们的散列表不会存放重复的值。五. 总结概括equals 和 hashCode 方法是 Object 类中的方法而 Object 类是所有类的祖宗类所以每个类中都存在 equals 和 hashCode如果不重写就是默认 Object 类中的实现当我们重写 equals 后如果要放入哈希表中则要重写 hashCode 来保证不会重复放入相同的值。所以建议当重写了 equals 之后将 hashCode 一并重写