自定义对象作为HashMap的键,同时重写hashCode和equals方法

如果要将自定义类的实例 作为HashMap的 键,必须重写hashCode和equals方法

简单版本,看不懂看后面复杂版本解释

在这里插入图片描述

复杂版本解释

当我们用 HashMap存入自定义的类时,如果不重写这个自定义类的equals和hashCode方法,得到的结果会和我们预期的不一样。我们来看 WithoutHashCode.java这个例子。

在其中的第 2到第 18行,我们定义了一个 Key类;在其中的第 3行定义了唯一的一个属性 id。当前我们先注释掉第 9行的 equals方法和第 16行的 hashCode方法。
在这里插入图片描述
在 main函数里的第 22和 23行,我们定义了两个 Key对象,它们的 id都是 1,就好比它们是两把相同的都能打开同一扇门的钥匙。

在第 24行里,我们通过泛型创建了一个HashMap对象。它的键部分可以存放 Key类型的对象,值部分可以存储String类型的对象。

在第 25行里,我们通过 put方法把 k1和一串字符放入到 hm里;而在第 26行,我们想用 k2去从HashMap里得到值;这就好比我们想用 k1这把钥匙来锁门,用 k2来开门。这是符合逻辑的,但从当前结果看, 26行的返回结果不是我们想象中的那个字符串,而是 null。
原因有两个:一是没有重写hashCode方法,二是没有重写equals方法

当我们往HashMap里放 k1时,首先会调用 Key这个类的 hashCode方法计算它的 hash值,随后把 k1放入hash值所指引的内存位置。

关键是我们没有在 Key里定义 hashCode方法。这里调用的仍是 Object类的 hashCode方法(所有的类都是Object的子类),而 Object类的 hashCode方法返回的 hash值其实是 k1对象的 内存地址(假设是1000)。
在这里插入图片描述
如果我们随后是调用 hm.get(k1),那么我们会再次调用 hashCode方法(还是返回 k1的地址 1000),随后根据得到的 hash值,能很快地找到 k1。
但我们这里的代码是 hm.get(k2),当我们调用 Object类的 hashCode方法(因为 Key里没定义)计算 k2的 hash值时,其实得到的是 k2的内存地址(假设是 2000)。由于 k1和 k2是两个不同的对象,所以它们的内存地址一定不会相同,也就是说它们的 hash值一定不同,这就是我们无法用 k2的 hash值去拿 k1的原因。
当我们把第 16和 17行的 hashCode方法的注释去掉后,会发现它是返回 id属性的 hashCode值,这里 k1和 k2的 id都是1,所以它们的 hash值是相等的。
我们再来更正一下存 k1和取 k2的动作。存 k1时,是根据它 id的 hash值,假设这里是 100,把 k1对象放入到对应的位置。而取 k2时,是先计算它的 hash值(由于 k2的 id也是 1,这个值也是 100),随后到这个位置去找。
但结果会出乎我们意料:明明 100号位置已经有 k1,但第 26行的输出结果依然是 null。其原因就是没有重写 Key对象的 equals方法。

下面可能有点绕

HashMap是用链地址法来处理冲突,也就是说,在 100号位置上,有可能存在着多个用链表形式存储的对象。它们通过 hashCode方法返回的 hash值都是100。
在这里插入图片描述
当我们通过 k2的 hashCode到 100号位置查找时,确实会得到 k1。但 k1有可能仅仅是和 k2具有相同的 hash值,但未必和 k2内容相等( k1和 k2两把钥匙未必能开同一扇门),这个时候,就需要调用 Key对象的 equals方法来判断两者是否相等了。
由于我们在 Key对象里没有定义 equals方法,系统就不得不调用 Object类的 equals方法。由于 Object的固有方法是根据两个对象的内存地址来判断,所以 k1和 k2一定不会相等,这就是为什么依然在 26行通过 hm.get(k2)依然得到 null的原因。
为了解决这个问题,我们需要打开第 9到 14行 equals方法的注释。在这个equals方法里,只要两个对象都是 Key类型,且它们的 id相等,它们内容就相等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/15016.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL库表操作作业

创建数据库 mysql> create database Market; mysql> use Market; 创建表和约束 mysql> create table customers(c_num int(11) primary key not null UNIQUE Key auto_increment , -> c_name varchar(50), -> c_city varchar(50), -> c_birth datetime…

【华为认证】HCIP-Datacom 2023最新题库

正在备考华为认证的小伙伴应该知道,除了理论知识外,刷题也相当重要,周工这里有一份HCIAHCIP-Datacom带解析的最新题库 点赞留言 即可领取。 1. (多选题)ISIS的Hello报文主要分为哪几种类型? A.P2P LAN IIH B.…

Pytorch-ResNet50-MINIST Classify 网络实现流程

分两个文件讲解:1、train.py训练文件 2、test.py测试文件. 1、train.py训练文件 1)从主函数入口开始,设置相关参数 # 主函数入口 if __name__ __main__:# ----------------------------## 是否使用Cuda# 没有GPU可以设置成Fasle# -…

SPEC CPU 2006 在 CentOS 5.0 x86_64 古老系统测试【2】

上一篇 SPEC CPU 2006 在 CentOS 5.0 x86_64 古老系统测试_hkNaruto的博客-CSDN博客 虚拟机时间,一天后获得结果 由于ssh版本太低,采用nc把文件拷贝出来 结果 SPEC CFP2006 Result Copyright 2006-2023 Standard Performance Evaluation Corporatio…

SpringBoot集成Quartz集群模式

<!-- quartz定时任务 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId></dependency> 单机版本&#xff1a; SpringBoot集成Quartz动态定时任务_jobgroupname_小…

09_Linux内核定时器

目录 Linux时间管理和内核定时器简介 内核定时器简介 Linux内核短延时函数 定时器驱动程序编写 编写测试APP 运行测试 Linux时间管理和内核定时器简介 学习过UCOS或FreeRTOS的同学应该知道, UCOS或FreeRTOS是需要一个硬件定时器提供系统时钟,一般使用Systick作为系统时钟…

人工智能(pytorch)搭建模型17-pytorch搭建ReitnNet模型,加载数据进行模型训练与预测

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能(pytorch)搭建模型17-pytorch搭建ReitnNet模型&#xff0c;加载数据进行模型训练与预测&#xff0c;RetinaNet 是一种用于目标检测任务的深度学习模型&#xff0c;旨在解决目标检测中存在的困难样本和不平衡…

Maven学习

1.配置环境变量 1.M2_HOME Maven的安装目录 2.修改Path %M2_HOME%\bin2.配置IDEA 配置文件的地址 本地仓库的地址 修改配置文件的路径 修改本地仓库的目录 注意&#xff0c;这里的路径的分隔符必须是/ 配置镜像 <mirror><id>aliyunmaven</id><mi…

在idea中使用Git技术

1.配置git环境 打开idea,点击file->setting->搜索git&#xff0c; 将git的安装路径填写进去 2.去gitee创建一个远程仓库 3.拉入一个.gitignore文件&#xff0c;过滤掉不需要管理的文件 4.在idea进行如下操作 5.选择要提交的内容 目前只是保存在了本地仓库 6.推送到远端…

SEGA: Semantic Guided Attention on Visual Prototype for Few-Shot Learning

方法比较简单&#xff0c;利用语义改进prototype&#xff0c;能促进性提升

十二、Docker Compose 介绍与安装

学习参考&#xff1a;尚硅谷Docker实战教程、Docker官网、其他优秀博客(参考过的在文章最后列出) 目录 前言一、docker compose介绍二、docker compose能干嘛三、docker compose安装与卸载3.1 docker-compose安装3.2 docker-compose卸载 总结 前言 在使用k8s之前&#xff0c;随…

LNMP架构及部署、skyuc电影网站部署

目录 一、安装nginx 1、关闭防火墙 2.创建管理nginx用户 3.配置nginx 4.命令优化 5.创建nginx脚本 二、安装mysql数据库 三、安装PHP 1.上传php安装包 2.上传 zend-loader-hph5.6 3.创建用户 四、LNMP平台中部署skyuc电影网站 1.解压 SKYUC.v3.4.2.srouce 2.创建数据…