简答版
因为我们在使用 HashMap 或 HashSet 集合类的时候,需要用到哈希表,哈希表必须满足 两个对象 equals 返回 true时,两个对象 hashCode 返回的哈希值必须相同,而我们重写equals方法后,可能导致两个对象 equals 返回 true ,而 hashCode 返回的哈希值不相同,导致哈希表中存储了两个相同的对象
详答版
我们知道
- 当两个对象 equals 返回 true 时,则两个对象就是相同的
- 哈希表中不能存储两个相同的元素
而 哈希表 的原理是
- 先比较两个对象的哈希值,如果哈希值不同,则这两个对象不可能相同,无需调用 equals 方法进行比较
- 如果哈希值相同,这两个对象不一定相等,因此会再使用 equals 方法进行比较,来确定这两个对象是否相等
- 并且哈希表中不能存储两个相同的元素
因此 equals 方法 和 hashCode方法必须满足
- hashCode相同时,equals 方法不一定返回 true
- equals 方法返回 true 时,两个对象 hashCode 返回的哈希值必须相同
而如果重写了 equals 方法,而没有重写 hashCode 方法,就有可能导致 equals 返回true,而hashCode 返回的哈希值不相同
那么哈希表在存储数据的时候,比较到两个对象的哈希值不相同,就认为两个对象不同,不在调用equals方法,将两个对象都存储在哈希表中,这就导致了哈希表的错误
我们看下面的一个例子
import java.util.Objects;public class Student {String name;int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(name, student.name);}}
上面的Student类我们重写了equals方法,但没有重写hashCode方法,然后进行测试
public class Test {public static void main(String[] args) {Student student01=new Student("张三",18);Student student02=new Student("张三",18);System.out.println(student01.equals(student02));Set<Student> studentSet = new HashSet<>();studentSet.add(student01);studentSet.add(student02);System.out.println(studentSet);}}
我们看到 HashSet 是 不可重复 的集合,却存入了两个相同的对象
现在我们重写hashCode方法
import java.util.Objects;public class Student {String name;int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}
在进行相同的测试
我们看到了这次就存储进一个对象
结论
重写equals方法的时候一定要重写hashCode方法
我们在自定义类的时候,equals方法默认使用 == 比较对象地址,而我们一般会重写以比较对象属性,而在idea中,当我们重写equals方法的时候,会自动帮我们重写hashCode方法