引言

原文链接:深入理解equals和hashCode 由于hashCode与HashMap有一定关系,推荐大家看一下我的这篇文章 HashMap源码大剖析

本文介绍java.lang.Object类中的两个方法:equals和hashCode。这两个方法大家应该都知道,但是这两个方法的作用是什么、为什么重写equals还要重写hashCode、它们之间有什么关系和约定等,或许有些小伙伴还不是很清楚,知其然知其所以然,今天就来带大家了解一下。

百度搜索"为什么重写equals一定要重写hashcode",第二条结果就是我写的文章。这是我很久之前写的,其中的内容表述得不太清楚,或多或少难以让人信服,于是我决定再写一篇。

1、hashCode

在阅读下面的内容之前,大家可能需要先了解一下什么是哈希表、哈希函数,这是数据结构相关的知识。

hashCode即散列码。散列码是用一个int值来代表对象,它是通过将该对象的某些信息进行转换而生成的。

Object类中默认的hashCode方法如下。

public native int hashCode();

这是一个本地方法,不同的虚拟机有不同的实现(具体实现自己看虚拟机源码哈)。Object默认的hashCode是根据对象的内存地址转化而来的,它是唯一的。

我们可以在自己的类中覆盖hashCode方法,但我们可以使用System.identityHashCode(Object x)方法返回默认的hashcode,无论对象是否覆盖默认的hashcode。

hashCode方法主要是为了给诸如HashMap这样的哈希表使用。

设计hashcode最重要的因素是:对同一个对象调用hachCode()应该产生同样的值(前提是对象的信息没有被改变)。

设计一个hashCode,它必须快,而且具有意义(使用有意义的字段来生成hashcode)。hashCode不需要唯一(默认的hashCode唯一),因此更应该关注它的速度,而不是唯一性。

由于在生成桶(桶指哈希桶,或哈希表的槽位)的下标前,hashcode还要做进一步处理,所以生成的hashCode范围不是很重要,是int就行。

好的hashCode()应该产生分布均匀的散列码。

哈希桶的大小最好是2的n次方。

  • 对现代处理器来说,除数和求余是最慢的操作,而使用2的n次方,可以用位运算代替求余(%开销较大)。

  • 举个例子,假设哈希桶大小为16(HashMap初始大小),假设hashCode为20,那么使用%求余会得到下标4;但这可以用hashCode&(length-1)代替,即20&(16-1),结果也是4。

2、equals

hashCode并不需要唯一性,但equals必须严格地判断两个对象是否相同。

正确的equals方法有如下特性:

  • 自反性:x.equals(x)一定返回true

  • 对称性:如果x.equals(y)为true,那么y.equals(x)也为true

  • 传递性:如果x.equals(y)为true、y.equals(z)为true,那么x.equals(z)也为true

  • 一致性:如果x和y中用于等价比较的信息没有改变,那么x.equals(y)无论调用多少次,结果都一致

  • 任何不是null的x,x.equals(null)一定返回false

3、equals与hashCode的相关规定

之所以有规定,是为了使诸如HashMap这样的哈希表正常使用。具体规定如下:

  1. equals相等,hashcode一定相等。

  2. equals不等,hashcode不一定不等。

  3. hashcode不等,equals一定不等。

  4. hashcode相等,equals不一定相等。

因此,如果我们重写了equals,那么必须重写hashCode,使其满足这些规定。当然,如果我们不把自定义对象当成HashMap的键来使用,那么自定义对象不重写equals和hashCode也是可以的。

下面来详细解释一下,为什么这些规定能让HashMap正常工作。

3.1、equals相等,hashCode一定相等

因为HashMap是用equals判断键是否相等的,用反证法,如果两个键 equals相等,而hashcode不等的话,那么就无法保证通过hashcode计算的下标值相等,下标值不等也就意味着相等的两个键却 到了不同的值,这肯定是不对的。

3.2、equals不等,hashcode不一定不等

equals不等,一般hashcode也不相等,这是为了尽量减少哈希冲突。但为啥会出现相等的情况呢,因为hashcode是int类型,是有范围的,当数据量很大的情况下,难免会发生冲突,此时HashMap通过拉链法解决冲突。

当从map中获取equals不等的两个键时,由于它们的hashcode相同,所以计算到的下标值也相同,当定位到同一个桶位时,会在单链表上顺序查找,查找到的依据就是要查找的键与单链表上的键equals相等。

3.3、hashcode不等,equals一定不等

这个相当于规定1的逆反命题。

3.4、hashcode相等,equals不一定相等

这个相当于规定2的逆反命题。如果两个键hashcode相等,那么计算到的下标值是相同的,这时候两个键可能是相等的(该桶位有一个元素),也可能是不等的(该桶位有两个元素)。

彻底搞懂为什么重写equals还要重写hashcode?相关推荐

  1. Java 细品 重写equals方法 和 hashcode 方法

    前言 在我们需要比较对象是否相等时,我们往往需要采取重写equals方法和hashcode方法. 该篇,就是从比较对象的场景结合通过代码实例以及部分源码解读,去跟大家品一品这个重写equals方法和h ...

  2. 为什么重写equals()就要重写hashCode()

    文章目录 一.前言 二.hashCode()方法 三.equals()方法 四.hashCode() 与 equals() 4.1 不会创建"类对应的散列表"的情况 4.2 会创建 ...

  3. HashSet要重写equals方法和hashCode方法

    注:重要笔记在代码中注释有 hashSet去重: 即判断两个对象是否相等 1:会先调用对象的hashCode方法获得hash的值,如果set中哈希表里面没有对应的hash值,则将次对象存入set中 2 ...

  4. java重写6,java重写equals()方法和hashCode()方法

    1.equals()方法和hashCode()方法是什么? equals()和hashCode()都是是Java中万物之源Object类中的方法: equals方法用于比较两个对象是否相同,Objec ...

  5. JAVA正确地自定义比较对象---如何重写equals方法和hashCode方法

    在实际应用中经常会比较两个对象是否相等,比如下面的Address类,它有两个属性:String province 和 String city. public class Address {privat ...

  6. 面试必备之为什么重写equals必须重写hashcode

    印象中是来自 https://github.com/Snailclimb/JavaGuide Object.hashcode的通用约定为: 1.在一个应用执行期间,如果一个对象的equals方法做比较 ...

  7. java中重写hashcode_Java中HashSet要重写equals方法和hashCode方法

    下面给出一个属性不同但哈希码相同的例子: import java.util.HashSet; import java.util.Iterator; import java.util.Set; clas ...

  8. 为什么重写equals一定要重写hashcode?

    引言 这篇文章已经是我很久之前写的,其中的内容表述得不太清楚,或多或少难以让人信服,于是我又写了一篇,链接如下: CSDN链接:彻底搞懂为什么重写equals还要重写hashcode?  微信公众号链 ...

  9. 为什么重写equals一定要重写hashCode方法?

    大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白. 下面我们看下Objec ...

最新文章

  1. android 反编译_Android 反编译实战
  2. Linux 静态库 动态库
  3. Linux有问必答:如何为在Linux中安装兄弟牌打印机
  4. 如何使用DNN中的Calendar控件
  5. Java教程:Java continue语句详解
  6. LIO-SAM探秘第三章之代码解析(五) --- imuPreintegration.cpp
  7. WMI 错误 10的解决
  8. Fortran入门教程(九)——文件
  9. 英伟达驱动更新记录_手把手教你如何通过NVIDIA(英伟达显卡)官网及时更新升级显卡驱动程序版本-网络教程与技术 -亦是美网络...
  10. HikariCP数据库连接池详解
  11. UWB三维定位方式概述
  12. 【气动学】基于龙格库塔算法实现外弹道仿真含Matlab源码
  13. PS--解决文字不清晰问题
  14. 腾讯优图实验室贾佳亚:加入优图第一年 | 专访
  15. Vue中3.0版本严格模式运行项目报错
  16. 李沐精读论文:MAE 《Masked Autoencoders Are Scalable Vision Learners》
  17. python绘制动漫人物图片女生可爱_绘画动漫人物图片女生唯美
  18. android 环境一键,一键切换Android应用环境(Environment Switcher)
  19. 基于java安防管理平台计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署
  20. 云米递交招股书:上半年净利7029万 雷军系持股40%

热门文章

  1. 第41章 RS-485通讯实验—零死角玩转STM32-F429系列
  2. 格式化字符串漏洞利用 一、引言
  3. 测量设备校准/验证后,如何判定是否符合有关规范?
  4. 黑苹果适合什么用途?_特定用途有特别要求,不是什么硬盘都适合NAS系统
  5. 用java设计实现一个简单的动作冒险类游戏
  6. 苹果语音备忘录怎么改名字_苹果手机语音备忘录怎么恢复?教你在手机上直接操作...
  7. lammps 案例in文件汇总
  8. 语法体系:揭秘同位语从句day9
  9. 第五章 我来帮你(一)
  10. Tagoram: Real-Time Tracking of Mobile RFID Tags to High Precision Using COTS Devices