全网最细致之为什么重写equals方法需要重写hashcode

文章讲述了Java中equals方法和hashCode方法的作用,为什么在重写equals方法时需要重写hashCode,以及这两个方法如何影响Set集合的去重逻辑。作者通过实例演示了未重写和重写后的效果差异。
摘要由CSDN通过智能技术生成

很多小白在接触java时都会存在一个疑问为什么重新equals方法一定要重新hashcode,废话不多说,我们开始讲解!

为什么需要重新equals方法?

重新equals方法主要时根据一些具体业务有关系,我们现在简单举例假设有一个User类包含了name和age属性。

public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

}

针对上述User类,我们尝试创建两个属性相同的对象来判断是否相等!

public class main {
    public static void main(String[] args){
        User u1 = new User("zhangsan", 123);
        User u2 = new User("zhangsan", 123);
        System.out.println(u1.equals(u2));

    }
}

结果会是什么呢?会是false!Java 中的 equals 方法是比较对象的引用是否相等,而不是对象的内容。因此,当你调用 equals 方法比较 u1u2 时,实际上是在比较两个对象的引用地址,而不是比较它们的属性值。当然如果是基本类型肯定直接比较值了,可惜u1和u2是引用类型!

所以为了让u1和u2属性值相同,就相等,我们就需要重写equals方法!具体如下:

public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object obj) {
        if (this==obj) return true;
        if (obj==null||this.getClass()!=obj.getClass()) return false;
        User u1 = (User) obj;
        return this.age== u1.age&& Objects.equals(this.name,u1.name);
    }

}

hashcode方法有什么用?

hashCode 翻译为中文是散列码,它是由对象推导出的一个整型值,并且这个值为任意整数,包括正数或负数。​

需要注意的是:散列码是没有规律的。如果 x 和 y 是两个不同的对象,x.hashCode() 与 y.hashCode() 基本上不会相同;但如果 a 和 b 相等,则 a.hashCode() 一定等于 b.hashCode()。​

为什么重写equals也要重写hashcode?

以Set集合为例,Set集合不能存储重复元素。什么样的元素是重复元素?它是按照下述方法进行判定的!!!先判断两个对象的hashcode是否相同,如果相同说明在哈希表的位置是一样的【因为hashcode作用是确定对象在hash表中的位置】,判断出一个位置相同后再进行equals进行比对内存地址是否相等。如果hashcode相同且equals也相同则是重复元素则会去重!。

下面还是以刚才的u1和u2对象为例子,我们已经知道了u1和u2重写了equals方法,但是没有重写hashcode方法,所以他们的hahcode会相同吗?当然是不同的,因为我new两个user对象【u1、u2】他们都的内存地址是不一样的,所以hashcode由内存地址转换为整数也必然不相同。


public class main {
    public static void main(String[] args){
        User u1 = new User("zhangsan", 123);
        User u2 = new User("zhangsan", 123);
        System.out.println(u1.hashCode());
        System.out.println(u2.hashCode());

    }
}

当我们往Set集合中存放时,u1和u2都能放进去因为虽然equals判断他俩相等,但是hashcode没有重写所以根据上述判断是否是重复元素的规则【1.hashcode是否相等2.调用equals方法是否相等】的第一层就没通过,则u1和u2都可以放进去set集合中,不判定为重复元素。

public class main {
    public static void main(String[] args){
        User u1 = new User("zhangsan", 123);
        User u2 = new User("zhangsan", 123);
        Set<User> s=new HashSet<>();
        s.add(u1);
        s.add(u2);
        System.out.println(s.size());
    }
}

所以重写了equals需要重写hashcode方法,不然会破坏set的去重性。

当我们重写了hashcode方法时

public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object obj) {
        if (this==obj) return true;
        if (obj==null||this.getClass()!=obj.getClass()) return false;
       User u1 = (User) obj;
       return this.age== u1.age&& Objects.equals(this.name,u1.name);
    }
   @Override
    public int hashCode() {
        return Objects.hash(name,age);
    }
}

此时u1和u2的hashcode相等了

public class main {
    public static void main(String[] args){
        User u1 = new User("zhangsan", 123);
        User u2 = new User("zhangsan", 123);
        System.out.println(u1.hashCode());
        System.out.println(u2.hashCode());
    }
}

因此重写了equals和hashcode方法以后,上述u1和u2会变为相同对象,也不会影响set的去重性

public class main {
    public static void main(String[] args){
        User u1 = new User("zhangsan", 123);
        User u2 = new User("zhangsan", 123);
        Set<User> s=new HashSet<>();
        s.add(u1);
        s.add(u2);
        System.out.println(s.size());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值