equals和==的区别,为什么重写equals要重写hashCode

区别

== 分两种情况:

  1. 若比较的是基本数据类型,则比较的是值,只要值相等,就可以
  2. 若比较的是引用数据类型,则比较的是内存地址。

equals 也是分两种情况:

  1. 没有重写equals()。通过equals比较俩对象的时候,和==一样的,比较的是内存地址值。
  2. 重写了equals()方法。一般我们通过重写equals()方法来比较两个对象的内容是否相等。(String中重写了equals()方法,是比较的两个对象的值)

(例子) 没有重写equals

package fuxi.Hascode;

import java.util.HashSet;
import java.util.Objects;

public class Student {
    private String name;
    private int age;
    Student(int age){
        this.age=age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
 public static void main(String[]args){
        Student stu=new Student(23);
        stu.name="zrf";
        Student stu1=new Student(23);
        stu1.name="zrf";
        HashSet set=new HashSet();
        set.add(stu);
        set.add(stu1);
        for(Object s:set){
            System.out.println(s);
        }
        HashSet set1=new HashSet();
        set1.add("1");
        set1.add("1");
        for(Object s:set1){
            System.out.println(s);
        }
    }
}

按道理因为hashset不能存储一样的值,那么set1和set应该都只有一个值,但是我们的结果却是:

Student{name='zrf', age=23}
Student{name='zrf', age=23}
1

这是为什么?

set1中我们添加的是String,因为String中的equals被重写过,所以它只比较内容是不是一样。
set中我们添加的是Student,当set1添加stu时,set为空,直接添加,当添加stu1时,先比较是否有相同的hashcode,此时调用的是Object中的euqals,比较的是内存地址值,因为stu1与stu是都是new出来的,属于不同的对象,所以内存地址值不同,所以set会直接存入stu1.

正确的写法(重写equals)

package fuxi.Hascode;

import java.util.HashSet;
import java.util.Objects;

public class Student {
    private String name;
    private int age;
    Student(int age){
        this.age=age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }


    @Override
    public 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);
    }

    @Override
    public int hashCode() {

        return Objects.hash(name, age);
    }
    public static void main(String[]args){
        Student stu=new Student(23);
        stu.name="zrf";
        Student stu1=new Student(23);
        stu1.name="zrf";
        HashSet set=new HashSet();
        set.add(stu);
        set.add(stu1);
        for(Object s:set){
            System.out.println(s);
        }
        HashSet set1=new HashSet();
        set1.add("1");
        set1.add("1");
        for(Object s:set1){
            System.out.println(s);
        }
    }
}

为什么重写equals的时候要重写hashCode

我们可以看到上面的代码中,重写equals的时候也重写了hashCode这是为什么?在下面的代码中,我们只重写了equals没有重写hashCode,发现结果与第一个一样。

package fuxi.Hascode;

import java.util.HashSet;
import java.util.Objects;

public class Student {
    private String name;
    private int age;
    Student(int age){
        this.age=age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }


    @Override
    public 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);
    }

//    @Override
//    public int hashCode() {
//
//        return Objects.hash(name, age);
//    }
    public static void main(String[]args){
        Student stu=new Student(23);
        stu.name="zrf";
        Student stu1=new Student(23);
        stu1.name="zrf";
        HashSet set=new HashSet();
        set.add(stu);
        set.add(stu1);
        for(Object s:set){
            System.out.println(s);
        }
        HashSet set1=new HashSet();
        set1.add("1");
        set1.add("1");
        for(Object s:set1){
            System.out.println(s);
        }
    }
}
Student{name='zrf', age=23}
Student{name='zrf', age=23}
1
原因:

就如上面的例子,我们往set中插入对象时,会先判断hashCode是否一样,如果重写了equals,而不重写hashCode,那么hashCode会用Object中的方法,而Object对象中的hashCode方法始终返回的是一个对象的hash地址,而这个地址是永远不相等的。所以这时候即使是重写了equals方法,也不会有特定的效果的,因为hashCode方法如果都不相等的话,就不会调用equals方法进行比较了,所以没有意义了。

hashCode()和euqals()有相关规定:

  1. 如果两个对象的内容不发生改变,无论发生多少次调用,它的hashCode值都是一样的。
  2. 如果两个对象根据equals(Object)方法比较是相等的,那么所产生的的hashcode必须一样。
  3. 如果两个对象产生的hashcode一样,两个对象也不一定相等。

引用:

https://blog.csdn.net/qq_33619378/article/details/92661494
https://baijiahao.baidu.com/s?id=1660514228207272623&wfr=spider&for=pc
https://www.cnblogs.com/Eason-S/p/5894743.html

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值