当前位置: 首页 > news >正文

java之hashCode() 方法和 equals(Object obj) 方法之间的关系

1、 hashCode() 方法和 equals(Object obj)

在Java中,hashCode() 方法和 equals(Object obj) 方法之间的关系是紧密相连的,特别是在使用基于哈希的集合(如 HashSetHashMapHashTable 等)时。这两个方法共同决定了对象在哈希表中的存储和检索行为。

hashCode() 方法

  • hashCode() 方法用于获取对象的哈希码。
  • 哈希码是一个整数,由对象的内部地址或根据对象的字段通过某种算法计算得到。
  • 哈希码的主要目的是在哈希表中减少碰撞(即不同的对象具有相同的哈希码)的概率,从而提高查找效率。

equals(Object obj) 方法

  • equals(Object obj) 方法用于比较两个对象是否相等。
  • 在没有重写 equals 方法的情况下,equals 方法比较的是对象的引用(即内存地址)。
  • 重写 equals 方法时,通常也会重写 hashCode 方法,以保持它们之间的一致性关系。

hashCode() 和 equals(Object obj) 之间的关系

  • 一致性(Consistency):对于任何非null的引用值x和y,当且仅当 x.equals(y)true 时,x.hashCode() 必须等于 y.hashCode()
  • 不同对象可以有相同的哈希码:两个不相等的对象(即 equals(Object obj) 返回 false)可以有相同的哈希码。
  • 如果两个对象相等:根据 equals(Object obj) 方法的定义,如果两个对象相等(即 equals(Object obj) 返回 true),那么对这两个对象中的每一个调用 hashCode() 方法都必须产生相同的整数结果。

为什么需要保持一致性

在基于哈希的集合中,当你尝试添加、查找或删除一个对象时,集合首先会计算该对象的哈希码,以决定它在哈希表中的哪个桶(bucket)中。然后,它会在该桶中遍历所有对象,使用 equals() 方法来查找确切的对象。

如果 hashCode() 方法没有与 equals() 方法保持一致,那么即使两个对象通过 equals() 方法被认为是相等的,它们也可能被放置在哈希表的不同桶中,导致无法正确找到对象,或者导致哈希表无法正确管理对象的存储和检索。

因此,当你重写 equals() 方法时,通常也需要重写 hashCode() 方法,以确保这两个方法之间的一致性。

2、不同对象可以有相同的哈希码的原因

在哈希表中,不同对象可以有相同的哈希码(也称为哈希冲突或哈希碰撞)的原因主要归结为哈希函数的有限性和对象的无限性之间的矛盾。

  1. 哈希函数的有限性:哈希函数的设计目标是将任意长度的输入(比如对象的状态或关键属性)映射到固定长度的输出(即哈希码,通常是整数)。由于输出空间是固定的,因此哈希函数只能产生有限数量的不同哈希码。

  2. 对象的无限性:在理论上,可以创建的对象数量是无限的,因为对象的属性可以有无限多种组合方式。即使只考虑有限的几个属性,这些属性的不同组合也会导致理论上无限多种不同的对象。

  3. 概率性:由于哈希函数的输出空间有限,而输入空间(即可能的对象集合)无限,因此必然存在多个不同的对象映射到同一个哈希码的情况。这是概率上的必然结果,尤其是在处理大量数据时。

  4. 性能与空间的权衡:哈希表的设计需要在性能(查找、插入和删除操作的平均时间复杂度)和空间(哈希表所需的内存)之间做出权衡。使用更复杂、输出范围更大的哈希函数可以减少哈希冲突,但会增加计算哈希码所需的时间和空间成本。相反,使用更简单、输出范围较小的哈希函数可以提高性能,但会增加哈希冲突的概率。

  5. 解决哈希冲突:为了处理哈希冲突,哈希表通常使用各种策略,如开放寻址法(open addressing)和链地址法(chaining,也称为分离链接法)。在链地址法中,每个桶(bucket)实际上是一个链表,所有具有相同哈希码的对象都被添加到同一个链表中。这样,即使不同对象具有相同的哈希码,它们也可以被正确地存储和检索。

因此,不同对象可以有相同的哈希码是哈希表设计中的一个固有特性,需要通过合理的哈希函数和冲突解决策略来管理。

3、介绍开放寻址法(open addressing)和链地址法(chaining,也称为分离链接法)

开放寻址法(Open Addressing)和链地址法(Chaining,也称为分离链接法)是两种解决哈希表中哈希冲突的主要方法。下面分别介绍这两种方法:

1. 开放寻址法(Open Addressing)

定义与原理

  • 开放寻址法是一种哈希表的冲突解决方法,它要求所有的元素都存储在哈希表的数组中。当发生冲突时,即两个不同的元素通过哈希函数计算得到的哈希值相同时,开放寻址法会寻找数组中的下一个空闲位置,直到找到一个空槽或遍历整个表为止。

实现方式

  • 线性探测(Linear Probing):当发生冲突时,依次检查下一个位置,直到找到一个空槽或者遍历整个表。公式为 hash(key, i) = (hash(key) + i) % tableSize
  • 二次探测(Quadratic Probing):根据一个二次方程的形式探测下一个位置,公式为 hash(key, i) = (hash(key) + c1 * i + c2 * i^2) % tableSize
  • 双重哈希(Double Hashing):使用两个哈希函数,第一个哈希函数计算出位置,如果发生冲突,则通过第二个哈希函数计算一个步长,再次寻找下一个位置。公式为 hash(key, i) = (hash1(key) + i * hash2(key)) % tableSize

优势与劣势

  • 优势:不需要额外的数据结构来存储相同哈希值的元素,节省空间。
  • 劣势:可能导致聚集(clustering)问题,即相邻的位置可能会被频繁占用,导致查找效率下降。同时,扩容和重新哈希的成本较高。

2. 链地址法(Chaining,分离链接法)

定义与原理

  • 链地址法是一种通过链表解决哈希冲突的方法。在哈希表的每个槽位上,不直接存储数据元素,而是存储一个指向链表的指针。所有映射到该槽位的数据元素都存储在链表中。

实现方式

  • 当哈希函数计算出的槽位已有元素时,将新元素添加到该槽位对应链表的末尾。
  • 查找、插入和删除操作都首先定位到槽位,然后在链表中进行。

优势与劣势

  • 优势:处理冲突简单,只需在链表末尾添加新元素。同时,链表的长度可以动态变化,适应不同数量的元素。
  • 劣势:在极端情况下,某些槽位的链表可能非常长,导致查找效率下降。此外,链表需要额外的空间来存储指针。

装填因子

  • 在链地址法中,装填因子α定义为哈希表中关键字记录总数N与哈希表大小M的比值,即α=N/M。它反映了哈希表的填充程度,对哈希表的性能有重要影响。

综上所述,开放寻址法和链地址法各有优缺点,选择哪种方法取决于具体的应用场景和需求。

相关文章:

java之hashCode() 方法和 equals(Object obj) 方法之间的关系

1、 hashCode() 方法和 equals(Object obj) 在Java中,hashCode() 方法和 equals(Object obj) 方法之间的关系是紧密相连的,特别是在使用基于哈希的集合(如 HashSet、HashMap、HashTable 等)时。这两个方法共同决定了对象在哈希表…...

首届「中国可观测日」圆满落幕

首届中国可观测日(Observability Day)在上海圆满落幕,为监控观测领域带来了一场技术盛宴。作为技术交流的重要平台,此次活动不仅促进了观测云与亚马逊云科技之间的深化合作,更标志着双方共同推动行业发展的重要里程碑。…...

[Docker][Docker NetWork][下]详细讲解

目录 1.网络管理命令1.docker network creatre2.docker network inspect3.docker network connect4.docker network disconnect5.docker network prune6.docker network rm7.docker network ls 2.docker bridge 详解0.基本概念1.默认 bridge2.自定义 bridge3.DNS解析4.端口暴露…...

安卓系统在未来如何更好地解决隐私保护与数据安全的问题?

安卓系统可以通过以下方式更好地解决隐私保护与数据安全的问题: 强化权限控制:安卓系统可以进一步加强对应用程序权限的管理,确保用户能够清楚地知道应用程序需要哪些权限,并给予用户更多的控制权,例如允许用户选择性地…...

MySQL innodb单表上限一般多少

参考:https://www.zhihu.com/question/351797203/answer/3137174084 1.MySQL innodb单表上限为啥都说是2k万条 2.GaussDB for MySQL 为啥可以突破单表2k万的限制 要讨论这两个问题,得先明确性下实际的DB部署环境 表是索引数据是放在磁盘上的&#xf…...

更小、更安全、更透明:Google发布的Gemma推动负责任AI的进步

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

基于Django框架的医疗耗材管理系统的设计实现-计算机毕设定制-附项目源码(可白嫖)48999

摘 要 在目前的形势下,科技力量已成为我国的主要竞争力。而在科学技术领域,计算机的使用逐渐达到成熟,无论是从国家到企业再到家庭,计算机都发挥着其不可替代的作用,可以说计算机的可用领域遍及生活、工作的各个方面。…...

物联网协议篇(1):modbus tcp和modbusRTU的区别是什么?

Modbus TCP和Modbus RTU是Modbus协议中的两种主要变体,它们在多个方面存在显著的区别。以下是它们之间的主要区别: 1. 物理层和数据传输方式 Modbus TCP (TCP/IP): 使用以太网作为物理层,通过TCP/IP协议进行通信。数据以数据包的形式在TCP连接上传输,具有较高的通信速度和…...

JVM系列 | 对象的消亡——HotSpot的设计细节

HotSpot 的细节实现 文章目录 HotSpot 的细节实现OopMap 与 根节点枚举根节点类型及说明HotSpot中的实现 OopMap 与 安全点安全点介绍如何保证程序在安全点上? 安全区域记忆集与卡表记忆集卡表 写屏障并发的可达性分析(与用户线程)并发可达性…...

vue 运行或打包过程报错 JavaScript heap out of memory(内存溢出)

安装 increase-memory-limit npm install increase-memory-limit 运行increase-memory-limit ./node_modules/.bin/increase-memory-limit 运行后会报以下错误: "node --max-old-space-size10240" 不是内部或外部命令,也不是可运行的程序…...

git分支提交方法

先下载最新代码 改动文件覆盖 cp 文件到~/file/ git add添加文件 git commit提交本地 建立分支 git diff .c git status -uno git add git commit git checkout -b issue-lyd git push origin issue-lyd...

从微架构到向量化--CPU性能优化指北

引入 定位程序性能问题,相信大家都有很多很好的办法,比如用top/uptime观察负载和CPU使用率,用dstat/iostat观察io情况,ptrace/meminfo/vmstat观察内存、上下文切换和软硬中断等等,但是如果具体到CPU问题,我…...

声声入耳,事事如意 爱可声「如意」助听器即将上市!

如意助听器 Charm 爱可声全新系列「如意」助听器即将上市! 此次新品充分考虑了不同听损以及年龄的用户需求, 融合三大强劲性能。 1、多群体覆盖,定制个性化方案 如意助听器针对不同听损程度的听障患者设计了不同款式助听器,贴…...

生物实验室设备文件采集如何才能质量和效率双管齐下?

生物实验室的设备文件采集是实验室运营、科研活动和数据科学实践应用中不可或缺的一环。通过数据采集,实验室可以优化资源配置、提高实验结果的准确性和可靠性、支持科研水平的提升,并确保数据的安全性和可追溯性。因此,实验室应高度重视设备…...

Framework源码整编、单编、烧录过程

目录 一.背景 二.整编方式 二.单编方式 三.烧录 一.背景 源码编译分为整编和单编,整编通常耗时较长,单编则速度很多,如果我们进行一个小的修改想要立马验证的话单编就很合适 二.整编方式 开始执行编译操作,总共三步. 执行source操作source build/envsetup.sh .执行lunc…...

TypeScript类型断言

TypeScript类型断言是TypeScript中一个强大且有用的特性,它允许开发者在编译时明确指定一个值的类型,即使TypeScript无法自动推断出这个类型。类型断言类似于其他编程语言中的类型转换,但它不会改变变量的运行时值,而只是告诉编译…...

Mallet:一款针对任意协议的安全拦截代理工具

关于Mallet Mallet是一款功能强大的协议安全分析工具,该工具支持针对任意协议创建用于安全审计的拦截代理,该工具本质上与我们所熟悉的拦截Web代理类似,只是通用性更强。 工具运行机制 Mallet建立在Netty框架之上,并且依赖于Net…...

【IEEE出版】第五届大数据、人工智能与软件工程国际研讨会(ICBASE 2024,9月20-22)

第五届大数据、人工智能与软件工程国际研讨会(ICBASE 2024)将于2024年09月20-22日在中国温州隆重举行。 会议主要围绕大数据、人工智能与软件工程等研究领域展开讨论。会议旨在为从事大数据、人工智能与软件工程研究的专家学者、工程技术人员、技术研发人…...

自修室预约小程序的设计

管理员账户功能包括:系统首页,个人中心,学生管理,公告通知管理,自修室管理,座位预约管理,预约取消管理,管理员管理,系统管理 微信端账号功能包括:系统首页&a…...

用于跟踪个人图书馆的BookLogr

什么是 BookLogr ? BookLogr 是一款网络应用,旨在帮助您轻松管理个人图书馆。这项自托管服务可确保您完全控制数据,提供安全且私密的方式来跟踪您拥有、阅读或希望阅读的所有书籍。您也可以选择向公众自豪地展示您的图书馆,与您的…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

EtherNet/IP转DeviceNet协议网关详解

一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...

网络编程(UDP编程)

思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...