为什么重写equals方法必须也要重写hashCode方法

目录

一、了解equals方法与hashCode方法

1、equals方法

2、hashCode方法

hashCode方法

hash值

3、分析

二、分析

1、equals在观感上的问题

2、只重写equals带来的问题

三、总结


一、了解equals方法与hashCode方法

1、equals方法

java顶级父类Object的equals方法源码

    public boolean equals(Object obj) {
        return (this == obj);
    }

可以看出equals方法底层通过”==“判断是否相等,即判断两个对象的地址是否相同

2、hashCode方法

hashCode方法

hashcode方法通过特定的算法,将对象的内存地址等所有信息映射为一个数组,即散列值

hash值

系统通过特定的算法,将散列值映射为一个定长的值,即hash值(哈希值)

hash值主要是用来在散列存储结构中确定对象的存储地址的,提高对象的查询效率

3、分析

如果两个对象通过equals判断相等,那么它们的地址和内容都一定相等,因此算出来的hashCode和hash值也一定相等

如果两个对象通过equals判断不相等,那么它们的地址一定不同,但是内容可能相等,算出来的hashCode和hash值有可能相等


二、分析

1、equals在观感上的问题

使用原生equals是通过两个对象的地址判断是否相等,这会导致一个问题,两个对象拥有完全相同的内容,但是equals判断不相等

    private String name;
    private Integer age;

    public test0830(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
        test0830 t1 = new test0830("张三",20);
        test0830 t2 = new test0830("张三",20);
        System.out.println(t1.equals(t2));

 

 在人的主观感受上,内容相同的两个对象是应该相等的,即使他们地址不同

因此可以重写equals方法,重写后只要内容完全相同,那么就返回true。但这会带来新的问题。

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

  

2、只重写equals带来的问题

在重写equals方法后,上面t1和t2两个对象经过判断是相等的

但是这两个对象的地址不同,他们的hash值也不同,当把这两个对象放进HashSet中,会有两个值,而不是去重后只有一个值

        HashSet<test0830> set = new HashSet<>();
        set.add(t1);
        set.add(t2);
        System.out.println(set.size());

 

为了解决这种问题,需要重写hashCode方法,让hashCode根据name和age来映射散列表,不再管内存地址

    @Override
    public int hashCode(){
        return Objects.hash(name,age);
    }

 

 这下HashSet实现了去重,问题解决


三、总结

根据人对”相等“的主观认识而重写的equals方法,如果不再根据对象的地址判断是否相等,HashSet就会出现不能去重的问题。因为此时hashCode方法仍然根据对象的内存地址生成不同的散列值,最终确定对象地址的hash值也会不同,影响HashSet中数据的存储。

HashSet

  • 用于存放对象
  • HashSet 是一个没有重复元素的集合。
  • 基于HashMap实现

HashMap

  • 存放键值对,key-value
  • key不可重复,value可重复
  • 底层基于数组+链表+红黑树实现,红黑树需要jdk≥1.8。

在HashMap底层中,数组的每一项都是个单链表,每个键值对根据key的hash值确定数组中的存放位置,再根据equals判断在链表上的位置。只重写equals,equals判断为true了,但是多个对象hashCode通过地址等信息算出来的散列值不同,那hash值也不同了,链表上的位置相同但是数组上的位置不同了,在hashMap中就会存到不同的位置,当于不重复,出现程序逻辑错误。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值