小白日更第四十五天->关于equals和hashcode

平时听到最多的就是重写equals方法就必须要重写hashcode方法,那到底是为什么呢?本着学习认真的态度,我就带着小伙伴们一起学习一下~
首先要了解的是equals()是Object类的方法。我们来看一下在Object类中equals是怎么被描述的:

equals位置

在这里插入图片描述
首先我们知道Object是所有类的父类也就是超类,我们看一下在Object中equals方法的实现是直接比较的是地址。我们知道基本类型和String都重写了equals方法。那我们先看一下我们经常使用的String类是怎么对equals方法进行重写的:

String重写equals

  public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

我简单分析一下:

1、首先判断地址是不是相等,如果地址相等那肯定是同一个字符串,直接返回true
2、如果地址不相等,判断一下是不是字符串类型,如果连字符串类型都不是也就没有比较的必要,直接返回false
3、如果是字符串类型就判断一下两个字符串的长度是不是相等,如果两个字符串的长度都不想等那肯定字符串的内容是不相等的
4、如果字符串的长度相等,再进行判断,一个字符一个字符的进行比较,期间发现只要有不相等就返回false
5、以上步骤执行完没有发现有不相等的字符,那两个字符串的内容也就相等了

String重写hashcode方法

在这里插入图片描述
以上就是我通过阅读源码,以我个人的理解来解释的,然后我们再看一下Integer类是如何重写equals的

Integer重写equals

在这里插入图片描述
相比于String,Integer就简单很多了。
1、先判断是不是Integer类型,类型不同直接返回false
2、类型相同把Integer转换为int类型然后进行数值大小的比较

到现在我们好像还是不知道为什么重写了equals方法就一定要重写hashcode方法,我们从一个集合类入手就是hashset,对集合有一定了解的同学都知道hashset可以保证不存放相同的元素,那hashset是怎么判读两个对象相等的呢,我们走进去看一下hashset的源码

hashset源码

构造函数
在这里插入图片描述
add方法
在这里插入图片描述
put方法
在这里插入图片描述
putVal方法
在这里插入图片描述
这个方法代码有些长,我只截取了部分。比较重要的两部分代码

if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);

计算数组下标,并对null做处理 ,(n - 1) & hash 确定元素存放在哪个桶中,如果桶为空,新生成结点放入桶中

 if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;

先比较hash值,这里提一下&&是一个短路操作,如果p.hash == hash是false,那就不用进行后面的比较了,小伙伴们都知道,如果hashcode相等,两个对象不一定相等,如果hashcode不等,两个对象一定不等,也就是说如果hashcode都不一样就没必要进行后面的比较了,一定是两个不同的对象,直接添加就ok了。

看一下hashcode的源码

在这里插入图片描述
调用的是本地方法,因为java的内存是安全的,所以不能根据散列码就直接得到对象的内存地址,但实际上,hashcode是根据对象的内存地址经哈希算法得来的。

所以现在我们大概知道了为什么重写equals方法的同时也要重写hashcode方法。在判断对象相等之前我们先对两个对象的hashcode做比较,如果hashcode值不相等那一定是两个不相等的对象,如果hashcode相等,那么有可能是同一个对象,也有可能是不同的对象,我们知道对象的hashcode值是根据hash算法散列在hash表上的,所以有一定的概率会产生hash冲突,所以我们判断两个对象的hasncode相等之后再进行equals判断,这样会省去一些比较的步骤。
Object中的equals方法比较的是两个对象是否具有相同的引用,它们一定是相等的。从这点上看,将其作为默认操作也是合乎情理的。然而,对于多数类来说, 这种判断并没有什么意义。 例如, 采用这种方式比较两个类的实例对象是否相等就完全没有意义。然而, 经常需要检测两个对象状态的相等性, 如果两个对象的状态相等, 就认为这两个对象是相等的。例如, 如果两个雇员对象的姓名、 薪水和雇佣日期都一样, 就认为它们是相等的(在实际的雇员数据库中,比较 ID 更有意义。)

以上就是我个人的理解,文章中有什么地方错了,希望小伙伴们在评论区中指正~~在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值