第九条:覆盖equals方法时总要覆盖hashCode方法
Object类的hashCode方法:
public native int hashCode(); 是一个本地方法。
其中这个方法的主要注释如下:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method
must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
在一次应用程序执行期间,只要对象的equals方法没有改变,那么对于同一个对象无论调用多少次hashCode方法,都应该返回同一个整数。
This integer need not remain consistent from one execution of an application to another execution of the same application.
在应用程序的多次执行时,调用hashCode方法,每次执行的返回整数可以不一样 。
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
如果两个对象根据equals方法返回的结果是true,即这两个对象是逻辑相等的,那么这两个对象的hashCode方法应该返回同一个整数。
It is not required that if two objects are unequal according to the {@link java.lang.Object#equals(java.lang.Object)} method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
如果两个对象根据equals方法返回的结果是false,即这两个对象不是逻辑相等的,那么这两个对象的hashCode方法可以返回同一个整数,也可以返回不同的整数,
但是,程序员应该认识到对于逻辑不相等的两个对象,它们的hashCode方法返回不同的整数,有可能提高散列表的性能。
在每个覆盖了equals方法的类中,必须覆盖hashCode方法,那么就会违反上面的hashCode的通用约定,这样导致该类无法结合所有基于散列的集合一起正常工作,
这样的集合包括HashMap,HashSet,Hashtable。
Object类的hashCode方法 ,为每个不同的实例对象返回不同的整数,如果我们覆盖了equals方法,而继承了hashCode方法,那么就算是两个逻辑相等的对象,对于hashCode方法来说,也是两个不同的实例对象,也返回的是不同的整数。
如何写一个好的hashCode方法:
自定义散列函数 ,产生的散列值,使得逻辑相同的对象有相同的散列值(放入同一个桶中),逻辑不同的对象有不同的散列值(放入不同的桶中)。
结合equals方法的关键域,有如下步骤:
1.把一个非零的常数值,如17,保存在一个名叫result的int变量中;
2.对于equals方法中的关键域产生int类型散列值:
boolean类型的域(如名叫f) 计算(f?1:0)
byte,char,short,int类型的域 计算 (int)f
long类型的域 计算 (int)(f^(f>>>32))
float类型的域 计算 Float.floatToIntBits(f)
double类型的域 计算 Double.doubleToLongBits(f)
引用类型的域 使用 引用类型的hashCode方法得到的散列值
数组类型的域 把数组中的每个元素当成一个关键域,计算出散列值。
3.对于每一个关键域计算出来的散列值 (如名叫c)
result = result * 31 + c;
最后放回这个result整数 就是计算出来的当前调用hashCode方法得到的散列值。
注意不要试图从散列值的计算过程中排除一个关键域来提高散列值计算的性能。
关于散列表:
相同散列值的对象被放入同一个桶中,这样寻找一个对象时,先算出这个对象的散列值,就知道到哪个桶中去找这个对象了 ,提高了查找性能。
第九条:覆盖equals方法时总要覆盖hashCode方法的更多相关文章
- 【Java实战】源码解析为什么覆盖equals方法时总要覆盖hashCode方法
1.背景知识 本文代码基于jdk1.8分析,<Java编程思想>中有如下描述: 另外再看下Object.java对hashCode()方法的说明: /** * Returns a hash ...
- 覆盖equals的时候总要覆盖hashCode
import java.util.HashMap; public class Student { private String name ; private String id; public Stu ...
- 半夜思考, 为什么建议重写 equals() 方法时, 也要重写 hashCode() 方法
我说的半夜, 并不是真正的半夜, 指的是在我一个人的时候, 我会去思考一些奇怪的问题. 要理解 hashCode() 需要理解下面三个点: hash契约 哈希冲突 哈希可变 第一点: hash 契约指 ...
- 覆盖equals时总要覆盖hashCode
本文涉及到的概念 1.为什么重载equals方法时,要重载hashCode函数;没有重载hashCode带来的问题 2.一个对象hashCode的生成规则 1.为什么重载equals方法时 ...
- JAVA中重写equals()方法的同时要重写hashcode()方法
object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true:注意:当此方法 ...
- Item 9 覆盖equals时总要覆盖hashCode
为什么覆盖equals时,总要覆盖hashCode? 原因是,根据Object规范: 如果两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCod ...
- 第9条:覆盖equals时总要覆盖hashCode
在每个覆盖equals方法的类中,也必须覆盖hashCode方法.否则,会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,包括HashMap,Hash ...
- Effective Java —— 覆盖equals时总要覆盖hashCode
本文参考 本篇文章参考自<Effective Java>第三版第十一条"Always override hashCode when you override equals&quo ...
- why在重写equals时还必须重写hashcode方法
首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashcode方法 public boolean equals(Object anO ...
随机推荐
- Luogu345: [POI2007]POW-The Flood
题意 见luogu Sol 贪心 从小到大枚举高度,把小于等于这一高度的相邻格子用并查集合并 那么这个集合内的所有格子都一定可以由这个集合内的一个最低点抽完水 那么合并之后(一定要在合并之后) 判断这 ...
- [HNOI2014]米特运输
显然知道一个节点就可以推出整棵树 然而直接乘会爆longlong 所以考虑取log 最后排序算众数即可 # include <stdio.h> # include <stdlib.h ...
- 云计算之路-阿里云上:docker swarm 集群再次出现故障
非常非常抱歉!16:30 ~ 17:00 左右我们用于跑 ASP.NET Core 站点的 docker swarm 集群再次出现宕机,由此给您带来了很大很大的麻烦,恳请您的谅解! 受此次故障影响的站 ...
- 为什么覆写equals必须要覆写hashCode?
============================================= 原文链接: 为什么覆写equals必须要覆写hashCode? 转载请注明出处! ============= ...
- PAT乙级-1043. 输出PATest(20)
给定一个长度不超过10000的.仅由英文字母构成的字符串.请将字符重新调整顺序,按"PATestPATest...."这样的顺序输出,并忽略其它字符.当然,六种字符的个数不一定是一 ...
- The method queryForMap(String, Object...) from the type JdbcTemplate refers to the missing type DataAccessException
Add spring-tx jar of your spring version to your classpath.
- Online Judge(OJ)搭建——3、MVC架构
Model Model 层主要包含数据的类,这些数据一般是现实中的实体,所以,Model 层中类的定义常常和数据库 DDL 中的 create 语句类似. 通常数据库的表和类是一对一的关系,但是有的时 ...
- 使用git指令下载github仓库代码(笔记)
通过Git指令下载源码 Git概念说明 三种状态:修改状态.暂存状态和Git仓库 基本的Git工作流程: 在工作目录中修改文件 暂存文件,将文件的快照放入暂存区域 提交更新,找到暂 ...
- Filecoin2017年Q4进度更新(完整版)
亲爱的Filecoin支持者.矿工.用户.投资者和广大的社区朋友们, 自从Token销售完成以后,我们便开始集中精力把Filecoin项目从设想变为现实-从实现Filecoin协议的核心代码到打造我们 ...
- LNMP详解
目录 Nginx配置 1 PHP解析 1 Mysql操作 3 服务安装 3 连接测试 3 数据配置 3 Blogs建立 4 LNMP 环境 Mysql:1 ...