一文搞懂==equals和hashcode

author author     2022-12-07     468

关键词:

面试的时候,经常会被问到==和equals()的区别是什么?以及我们也知道重写equals()时候必须重新hashCode()。这是为什么?既然有了hashCode()方法了,JDK又为什么要提供equals()方法呢?如果在重写equals()时候没有重写hashCode(),在使用HashMap或HashSet的时候可能会出现什么情况?

一文搞懂

== 和 equals()的区别是什么?

先来看看​

Java中使用==的时候,如果左右两边是基本类型和两边是应用类型的作用效果是不同的:

我们看看下面如下代码:

int x = 128;
int y = 128;
Person p = new Person(new Address("北京"));
Person p2 = p.clone();
System.out.println("两个基本类型==后值:");
System.out.println(x==y);
System.out.println("两个对象(引用类型)==后值:");
System.out.println(p == p2);
System.out.println(" \\n p的地址值为:"+p +" \\n p2的地址值为:"+p2.toString());

输出的结果是什么?

一文搞懂


从上面结果,我们可以得到如下结论:

需要注意:

因为 Java 只有值传递,所以,对于 == 来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址。

再看看equals()​

equals()方法特点:

1:equals()方法不能用于判断基本类型的变量,只能用来判断两个对象是否相等。

2:equals()方法存在于Object类中的。而我们又指导Object类是所有类的直接或者间接的父类。所以所有类都具有equals()方法

看看Object源码中equals()方法:

一文搞懂


从源码中我们可以看出,底层其实使用的是

== 左右两边都是对象。从上面我们知道==比较对象,其实就是比较对象内存中的地址值。

所以,我们可以得到equals()方法存在两种使用情况的结论:

1:类没有重写equals()方法:

当两个对象没有重写equals()方法时候,通过equals()方法进行比较的时候,其实就等价于通过"=="比较两个对象。因为在没有重新equals方法的情况下默认都使用的是Object类的equals()方法;

2:类重写了equals()方法:

一般在工作中,我们都重写equals()方法来比较两个对象中的属性是否相等。如果两个对象的属性相等,则返回true.就认为两个对象是相等的。


代码如下:

定义一个Girl对象,有两个属性:样貌和肤色。然后重写equals()方法

一文搞懂


测试重写了equals()方法后,两个girl通过equals比较:

一文搞懂


我们来看看输出的结果:

一文搞懂


equal()方法输入的是:true

但是实际上,两个Girl对象在堆中的内存地址值不一样。

我们在Girl对象中添加地址对象属性,在重写equals方法:

一文搞懂


测试:

一文搞懂

结果:

一文搞懂


从测试效果来看,可以验证结论:equals()比较两个重新equals()方法对象的时候,其实就是比较的是两个对象中每个属性值。

现在再来回答

接下来,我们在来看看hashCode()方法​

hashcCode是什么?

我们在调用对象的hashCode()方法的时候,返回的是一个int整数。这个整数其实是散列码,不过我们习惯称之为哈希码。作用就是确定这个对象在hash表中的所以位置。

出处:

hashCode()方法被定义在Object类中。这也就意味着任何一个类都有hashCode()这个方法(和equals()方法一样,都是被定义在Object对象中)。查看Object的源码,我们可以发现,次方法被native关键字修饰的。也就是说,Object中的hashCode()方法调用的是本地方法的。其实就是调用操作系统自己的hashCode()方法(用C语言或者是C++语言实现的)。该方法通常用来将对象的内存地址转换成整数后返回的。

一文搞懂


那么为什么要有hashCode?

起始hash存储的是键值对(K-V)形式的,其特点就是:能够根据"key"快速的检索出对应的"值"。在快速检索的时候,就使用到了哈希码。

回想下hashMap在put对象的时候,先计算出key对应的hashCode值,来判断对象需要加入的位置。如果不存在,就直接插入,如果存在,就加到链表中。如下图:

一文搞懂


从上面我们可以知道,起始

问题:既然两个方法都是比较对象是否相等,那么为什么JDK还要同时提供这两个方法呢?

答:为了提高效率。

还以hashMap的put方法为例,我们知道,先计算出hashCode,如果不存在,就可以直接put了。不用比较了,少了一次比较。效率就高了。

问题:那么能否只使用hashCode()方法呢?

答:不能。因为我们知道,哈希码是通过函数算出来的整数。既然使用的是公式,那么可能出现两个对象不一样,但是哈希码一样的。

就比如我们使用

经过公式计算的结果都是8,但是两个算式的a和b却是不相等的。

问题:如果两个对象的hashCode值相等,它们相等吗?

答:不相等。如:4+4 = 8;5+3=8;

通过上面说明,我们可以得到hashcode相关结论:

1:两个对象hashcode想的,那么这两个对象不一样相等(hash碰撞了。如:4+4 = 8;5+3=8;)

2:如果两个对象的hashCode值不相等,那么这两个对象就不相等

通过上面我们分析equals()方法,我们还可以得到下面这个结论:

3:如果两个对象的hashCode想的呢并且equals()方法返回的也是true。那么我们才能认为这两个对象相等的。

因为:4+4 = 8;4+4 = 8; 其中的8就是hashCode. 两个算式的 a、b都是4,也是相等的。

问题:为什么重写equals()时候必须重写hashCode()方法?

因为一般在重写equals()方法的时候,是要对两个对象进行比较的。如果两个对象相等的话,hashCode值必须相等,equals()方法判断两个对象也是相等的。

如果重写equals()方法时候,没有重写hashCode()方法的话,可能导致equals()方法判断想的的两个对象hashCCode值却不相等。如下示例:

一文搞懂


我们来看看结果:

一文搞懂


总结:

重写equals()方法是好,必须要重写hashCode()方法。


思考:重写equals()方法时候,没有重写hashCode()方法的haul,在使用HashMap/HashSet时候可能会出现什么问题?

我们以hashSet为例(hashSet底层使用的是hashMap来实现的):

一文搞懂


结果:

一文搞懂


(꒪ꇴ꒪(꒪ꇴ꒪ ;)哈? 不是说hashSet是唯一的,不能有重复的吗?打印出来的set集合大小是2啊,不是1啊。

其实,这就是只重写了equals(),没有重写hashCode()方法的后果。

因为在set.add()方法时候,先判断hashcode值,从上图我们可以看到,两个对象hashCode值不相等。set就认为不是一个对象,所以大小就是2了。

so,我们在重写equals()方法的时候,一定要重写hashCode()方法

hashcode和equals方法

分析:1:Person类1:姓名和年龄2:重写hashCode和equals方法1:如果不重写,调用Object类的equals方法,判断内存地址,为false1:如果是Person类对象,并且姓名和年龄相同就返回true2:如果不重写,调用父类hashCode方法1:如果equals方法相... 查看详情

hashcode和equals

hashCode()方法和equals()方法的作用其实是一样的,在Java里都是用来对比两个对象是否相等一致。那么equals()既然已经能实现对比的功能了,为什么还要hashCode()呢?因为重写的equals()里一般比较的比较全面比较复杂,这样效率就比较... 查看详情

hashcode()和equals()

区别、联系publicinthashCode():返回一个对象的哈希码值publicbooleanequals(Objectobj):判断两个对象是否相等,即是否指向同一内存地址;重写之后则比较的是两个对象的内容是否相等如果两个对象互相equals(),则hashCode()也必须相等hashC... 查看详情

equals()和hashcode()区别?

equals()和hashCode()区别?-------------------------------------------------equals():反映的是对象或变量具体的值,即两个对象里面包含的值--可能是对象的引用,也可能是值类型的值。hashCode():计算出对象实例的哈希码,并返回哈希码,又称... 查看详情

equals和==区别,equals和hashcode区别

...a和b的“==”返回的是false,而equals是true;2.equals相等,则hashcod 查看详情

equals和hashcode的联系

...比较的是内存地址;publicbooleanequals(Objectobj)return(this==obj);hashcode方法是native的,在c++中实现的;如果重写,java对象的equals和hashcode是这样规定的:1.相等的对象必须具有相同的hashcode值;  如果两个java对象A和B,A和B的euqals结果... 查看详情

java学习--equals和hashcode的关系

【JAVA编程】equals相等hashcode必然相等,反之不然2018年03月28日10:35:47 天路漫漫 阅读数:1786更多个人分类: 【JAVA】 1.equal()相等的两个对象他们的hashCode()肯定相等,也就是用equal()对比是绝对可靠。2.hashCode()相等的... 查看详情

为什么要重写equals和hashcode方法(代码片段)

equals hashcode 当新建一个java类时,需要重写equals和hashcode方法,大家都知道!但是,为什么要重写呢?需要保证对象调用equals方法为true时,hashcode必须相同.先看下面的例子:没有重写equals和hashcode方法User类publicclassUserprivateIntegerage;pr... 查看详情

理解equals(),hashcode()和==

这里分别讲==和equals()的关系,以及equals()和hashcode()的关系讲解之前,需要先明白对象的内容、对象的引用,基本类型,引用类型这几个概念,此处不做解释一、==和equals()两者都是比较"是否相同"这个概念。不同在于1、基本类型... 查看详情

关于equals与hashcode的重写

我想写的问题有三个:1、首先我们为什么需要重写hashCode()方法和equals()方法2、在什么情况下需要重写hashCode()方法和equals()方法3、如何重写这两个方法*********************************************************************第一个问题:为什么需要... 查看详情

从语言设计的角度探究java中hashcode()和equals()的关系(代码片段)

目录一.基础:hashCode()和equals()简介二.漫谈:引入hashCode()与equals()之间的关系三.解密:深入理解hashCode()和equals()之间的关系.四.验证:结合HashMap的源码和官方文档,验证两者的关系.一.基础:hashCode()和equals()简介在学习hashCode()和equals()之... 查看详情

equalsbuilder和hashcodebuilder(重写equal和hashcode)

EqualsBuilder和HashCodeBuilder自动化hashCode()和equals() 问题产生:当需要自动实现hashCode()和equals()方法 解决方法:使用EqualsBuilder和HashCodeBuilder  使用举例:  import  org.apache.commons.la 查看详情

为什么要重写equals()方法和hashcode()方法

Equals和HashCode方法是属于Object的,所以每个对象都有自己的equals和HashCode方法为什么要重写equals()方法1、equals()默认是比较的对象地址(源码见下图),而不是比较的对象的属性值,不符合我们的期望。特别指出八大包装对... 查看详情

重写equals和hashcode

packagecom.fz.song.hashCode;importjava.awt.*;/***Createdbysfzon2017/9/6.*/publicclassCat{privateStringname;privateintage;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name; 查看详情

==和equals以及hashcode

...变量使用。要想实现不同的equals功能可以对其进行重写。hashcode也是Object的方法,不能被基本类型调用。基于内存地址返回一个不固定位数的int型整数。同一个对象的hashcode一定是一样的。不同对象的hashcode也可 查看详情

hashcode和equals方法的区别与联系

equals:比较的是两个对象的内存地址值hashCode:比较的是两个对象在hash表中的位置hashCode的由来:对象的内存地址通过hash函数算法得到hashcode     1.equal()相等的两个对象他们的hashCode()肯定相等,也就是用equal()... 查看详情

为啥我需要覆盖 Java 中的 equals 和 hashCode 方法?

】为啥我需要覆盖Java中的equals和hashCode方法?【英文标题】:WhydoIneedtooverridetheequalsandhashCodemethodsinJava?为什么我需要覆盖Java中的equals和hashCode方法?【发布时间】:2022-01-0303:47:55【问题描述】:最近我通读了这个DeveloperWorksDocumen... 查看详情

为啥我需要覆盖 Java 中的 equals 和 hashCode 方法?

】为啥我需要覆盖Java中的equals和hashCode方法?【英文标题】:WhydoIneedtooverridetheequalsandhashCodemethodsinJava?为什么我需要覆盖Java中的equals和hashCode方法?【发布时间】:2019-01-2205:47:01【问题描述】:最近我通读了这个DeveloperWorksDocumen... 查看详情