Java equals()和hashCode()
介绍:
Java Object类提供了方法的基本实现– hashCode()和equals()。 这些方法非常有用,尤其是在使用Collection框架时。 哈希表实现依赖于这些方法来存储和检索数据。
在本教程中,我们将学习hashCode()和equals()之间的协定(它们的默认实现)。 我们还将讨论何时以及如何覆盖这些方法。
默认行为:
首先让我们看一下这些方法的默认实现:
存在于Object类中的equals()方法只是比较对象引用:
public boolean equals(Object obj) {return (this == obj);
}
因此,默认情况下, obj1.equals(obj2)与obj1 == obj2相同。
equals()方法比较诸如String等的类的实际值,因为它们在相应的类中被覆盖。
JDK中hashCode()方法的签名为:
public native int hashCode();
在这里, native关键字表示该方法是使用JNI (Java本机接口)以本机代码实现的。
hashCode()方法返回一个int类型。 默认情况下,返回值表示对象存储器地址。
实施原则:
在覆盖equals()和hashCode()方法之前,我们先来看一下准则:
1. equals(): 我们对equals()方法的实现必须是:
- 反身:对于任何参考值obj , obj.equals(obj)应该返回true
- 对称:对于参考值obj1和obj2 ,如果obj1.equals(obj2)为true,则obj2.equals(obj2)也应返回true
- 传递性:对于值OBJ1参考,OBJ 2和 OBJ 3,如果obj1.equals(OBJ 2) 真实 ,obj2.equals(OBJ 3)为真 ,那么obj1.equals(OBJ 3)也应该返回true
- 一致:只要我们没有更改实现, equals()方法的多次调用必须始终返回相同的值
2. hashCode():实现hashCode()时,必须考虑以下几点:
- 在一次执行中, hashCode()的多次调用必须返回相同的值,前提是我们不更改equals()实现中的属性
- 相等的对象必须返回相同的hashCode()值
- 两个或更多不相等的对象可以具有相同的hashCode()值
尽管在覆盖这些方法时要牢记上述所有原则,但是其中有一个流行的规则:
对于两个对象obj1和obj2 ,
- 如果obj1.equals(obj2),则obj1.hashCode()= obj2.hashCode()必须为true
- 但是,如果obj1.hashCode()== obj2.hashCode() ,则obj1.equals(obj2)可以返回true或false,即obj1和obj2可能相等或不相等
这通常被称为equals()和hashCode()契约。
为什么覆盖
hashCode()和equals()方法在基于哈希表的实现中存储和检索元素方面起着重要作用。 hashCode()确定给定项映射到的存储桶。 在存储桶中, equals()方法用于查找给定的条目。
假设我们有一个Employee类:
public class Employee {private int id;private String name;//constructors, getters, setters, toString implementations}
还有一个存储Employee作为键的HashMap :
Map<Employee, Integer> map = new HashMap<>();map.put(new Employee(1, "Sam"), 1);
map.put(new Employee(2, "Sierra"), 2);
现在我们已经插入了两个条目,让我们尝试一个containsKey()检查:
boolean containsSam = map.containsKey(new Employee(1, "Sam")); //false
尽管我们有Sam的条目,但是containsKey()返回false 。 这是因为我们尚未覆盖equals()和hashCode()方法。 默认情况下, equals()只会进行基于引用的比较。
覆盖
根据Javadocs:
当我们覆盖equals()方法时,我们还必须覆盖hashCode()方法。
这将有助于避免违反equals-hashCode合同。
请注意,如果我们违反合同,编译器不会抱怨,但是当我们将此类对象作为键存储在HashMap中时,最终可能会遇到意外行为。
我们可以使用IDE的功能快速覆盖这些方法。 使用Eclipse时,我们可以转到Source-> Generate hashCode()和equals()。 让我们看看为Employee类生成的实现:
public class Employee {...@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + id;result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Employee other = (Employee) obj;if (id != other.id)return false;if (name == null) {if (other.name != null)return false;} else if(!name.equals(other.name))return false;return true;}
}
显然,相同的字段已用于实现equals()和hashCode()方法,以与合同保持一致。
最佳做法:
使用equals()和hashCode()时应遵循的一些最佳实践包括:
- 实现hashCode()以在各个存储桶之间平均分配项目。 这样做的目的是最大程度地减少碰撞次数,从而获得良好的性能
- 对于equals()和hashCode()实现,我们应该使用相同的字段
- 在HashMap中将不可变对象作为键,因为它们支持缓存哈希码值
- 使用ORM工具时,请始终使用getter代替hashCode()和equals()方法定义中的字段。 那是因为有些字段可能是延迟加载的
结论:
在本教程中,我们首先研究了equals()和hashCode()方法的默认实现。 稍后,我们讨论了何时以及如何覆盖这些方法。
成为第一个发表评论的人。
翻译自: https://www.javacodegeeks.com/2019/05/java-equals-hashcode.html
Java equals()和hashCode()相关推荐
- 搞懂 Java equals 和 hashCode 方法
搞懂 Java equals 和 hashCode 方法 分析完 Java List 容器的源码后,本来想直接进入 Set 和 Map 容器的源码分析,但是对于这两种容器,内部存储元素的方式的都是以键 ...
- 理解Java中的hashCode 和 equals 方法
2019独角兽企业重金招聘Python工程师标准>>> 在Java里面所有的类都直接或者间接的继承了java.lang.Object类,Object类里面提供了11个方法,如下: 1 ...
- 程序猿的日常——Java基础之equals与hashCode
equals和hashCode是我们日常开发最常使用的方法,但是因为一般都使用默认的规则,因此也很少会引起关注.不过了解他们的用途和设计的原则,还是会帮助我们更好的设计代码. equals equal ...
- Java的equals() 和 hashCode()
2019独角兽企业重金招聘Python工程师标准>>> 首先,equals()方法和hashCode()方法都来自于Object类的定义,Java类都继承了这两个方法,都定义了自己的 ...
- Java实战equals()与hashCode()
2019独角兽企业重金招聘Python工程师标准>>> 一.equals()方法详解 equals()方法在object类中定义如下: 代码 public boolean equal ...
- Java基础提升篇:equals()与hashCode()方法详解
概述 java.lang.Object类中有两个非常重要的方法: public boolean equals(Object obj) public int hashCode() Object类是类继承 ...
- Java:重写equals()和hashCode()
http://blog.csdn.net/ansel13/article/details/5437486 很基础的东西就是由于没上心,三番五次地出错,这次好好总结下吧. 众所周之,String .Ma ...
- Java双等号,Equals(),HashCode()小结
默认情况 - 双等号==,比较的是内存地址. - equals(),默认比较的是内存地址. - hashCode(),默认返回的是object的内存地址. String中方法改写的情况 经常会遇到需要 ...
- java equals重写原则_java中为何重写equals时必须重写hashCode方法详解
前言 大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白. 在上一篇博文Ja ...
- Java:重写equals()和hashCode() 1
來源: 版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zhangjunhd.blog.51cto.com/113473 ...
最新文章
- 解决Oracle启动失败
- C++中类的静态成员变量和静态成员函数
- php隐藏文件链接,php隐藏文件实际下载地址的方法
- win10浏览器_Win10系统中ie浏览器的证书错误应该如何解决?
- docker启动失败,报docker dead but pid file exists,处理方式
- git 提示 error setting certificate verify locations !解决
- Java面向对象编程(高级)
- c语言 typedef_C Typedef-能力倾向问题与解答
- Java教程:Java String字符串和整型int的相互转换
- pandas.Series.values
- Crash Course经济学笔记
- USB转TTL、USB转232的区别
- Guitar Pro8最新2023中文免费吉他乐谱作曲练习工具
- Android Google地图接入(一)
- CS0012 错误。必须添加对程序集”xxxxx,Version=4.0.0.0,Culture=neutral,PublicKeyToken=xxxxxxx“的引用
- spotify能免费下歌吗_Spotify免费版与高级版:值得升级吗?
- 什么时候要把方法写成静态的。什么时候写成实例化方法。
- 使用Scrapy框架爬取88读书网小说,并保存本地文件
- 算法基础之二叉树理论
- xp 两个计算机互访,XP和Windows7文件不能互访解决办法