为什么重写 equals() 就一定要重写 hashCode() 方法

equals方法 

这个 equals 方法是 String 这个类里面的实现。
从代码中可以看到,当调用 equals 比较两个对象的时候,会做两个操作:
  1. 用==号比较两个对象的内存地址,如果地址相同则返回 true
  2. 否则,继续比较字符串的值,如果两个字符串的值完全相等,同样返回 true

为什么重写 equals() 就一定要重写 hashCode() 方法_第1张图片

hashCode方法

hashcode作用如下: 

  • 首先,Java 里面任何一个对象都有一个 native 的 hashCode()方法
  • 其次,这个方法在散列集合中会用到,比如 HashTable、HashMap 这些,当添加元素的时候,需要判断元素是否存在,而如果用 equals 效率太低,所以一般是直接用对象的 hashCode 的值进行取模运算

 对于散列集合:

  • 如果 table 中没有该 hashcode 值,它就可以直接存进去,不用再进行任何比较了;
  • 如果存在该 hashcode 值, 就调用它的 equals 方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址,所以这里存在一个冲突解决的问题,这样一来实际调用 equals 方法的次数就大大降低了 
hashCode 的值默认是 JVM 使用随机数来生成的,两个不同的对象,可能生成的HashCode 会相同。这种情况在 Hash 表里面就是所谓的哈希冲突,通常会使用链表或者线性探测等方式来解决冲突问题。但是如果两个完全相同的对象,也就是内存地址指向同一个,那么他们的 hashCode
一定是相同的。

为什么重写 equals() 就一定要重写 hashCode() 方法

在理论情况下,如果 x.equals(y)==true,如果没有重写 equals 方法,那么这两个对

象的内存地址是同一个,意味着 hashCode 必然相等。

为什么重写 equals() 就一定要重写 hashCode() 方法_第2张图片

但是如果我们只重写了 equals 方法,就有可能导致 hashCode 不相同。一旦出现这种情况,就导致这个类无法和所有集合类一起工作。所以,在实际开发中,约定俗成了一条规则,重写 equals 方法的同时也需要重写hashCode 方法。

当我们只是重写了equals 方法,下面new两个对象,在我们定义下是相同的类

为什么重写 equals() 就一定要重写 hashCode() 方法_第3张图片但是对于没有重写的code方法根据对象的内存地址生成哈希码的。所以我们两个new的对象的code不同,放入哈希集合里面就会存入重复相同对象

为什么重写 equals() 就一定要重写 hashCode() 方法_第4张图片

所以我们需要去重写hashcode方法

为什么重写 equals() 就一定要重写 hashCode() 方法_第5张图片 

总结

如果只重写 equals 方法,不重写 hashCode 方法。就有可能导致 a.equals(b)这个表达式成立,但是 hashCode 却不同。那么这个只重写了 equals 方法的对象,在使用散列集合进行存储的时候就会出现问题。 因为散列结合是使用 hashCode 来计算 key 的存储位置,如果存储两个完全相同的对 象,但是有不同的 hashcode 就会导致这两个对象存储在 hash 表的不同位置,当我们想根据这个对象去获取数据的 时候,就会出现一个悖论 一个完全相同的对象会在存储在 hash 表的两个位置,造成大家约定俗成的规则,出现 一些不可预料的错误。

你可能感兴趣的:(java面试题,java,开发语言)