为什么重写equals一定重写hashcode?
因为java某些容器在进行判断对象是否相等之前一般都是先进行hashcode判断hash值是否相等,才会进行equals的判断,所以有“对象相等,hashcode一定相等;而hashcode相等,对象不一定相等。”,原因是哈希表是结合了直接寻址和链式寻址两种方式,如下图:
以上图为例,就是将需要加入哈希表的数据首先计算哈希值,其实就是预先按行分组,hashcode就是每组的组号,hashcode相等说明是在同一组,所以可以看出hashcode并不代表所存储对象一定相同。这时就需要我们的equals来进行判断了,如果没有重写equals方法,那么它默认的是比较两个对象的地址值,也就相当于每组组员的编号,所以也有“equals相等,hashcode一定相等。”,equals都相等了,那就代表就是同一个对象了,那你的组号肯定也就相等了。
那么言归正传,为什么重写equals就一定要重写hashcode呢?因为java的某些容器(如HashSet)在添加对象的时候,会先调用hashcode来判断,如果hashcode值不一样就直接判断为两个不一样的对象进行存储,而在某些情况下,如:
Student student1 = new Student(1 , "李青");
Student student2 = new Student(1 , "李青");
System.out.println(student1.equals(student2));//true
我们重写了equals方法:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if(this.id != student.getId() || this.name != student.name) return false;
return true;
}
希望表达的意思是,学生类的学号与名字相同那么这个学生就是同一个人,我们放入容器中时也希望容器只存储一个对象,但因为比较的时候是先比较的hashcode,所以一上来就判断为了两个对象,然后就分别存储进了容器中,这也就产生了逻辑上的歧义,我就是一个人,你为什么要存两条我的记录呢?这也就违背了“equals相等,hashcode一定相等。”的规则,当然要记住规则不是原因,原因才是规则产生的前提条件。不要别人一问你为什么重写equals就一定要重写hashcode,你就回答个因为规定如此就好了。