float foo=42e1为什么错_为什么重写了equals()也要重写hashCode()

小Hub领读:

虽然是很基础的一篇文章,但是对于equals、hashcode两个方法,相信很多人都与其中的规则不熟悉,来跟着小Hub花个8分钟回顾一下!


作者:不学无数的程序员

https://my.oschina.net/u/4030990/blog/3134199

在 EffectiveJava中第九条规定在覆盖 equals()方法时总要覆盖 hashCode()方法。这是为什么呢?接下来我们就介绍一下这两个方法。

Java中的 equals()方法和 hashCode()方法都是在 Object类中的方法,而在Java中所有的类都是 Obejct类的子类,所以Java中所有的方法都会有这两个方法的默认实现。

equals方法

Object类中的 equals()方法定义如下

public boolean equals(Object obj) {

return (this == obj);

}

我们发现在 equals()方法中就关键的 ==,那么 ==在Java中有什么含义呢,我们都知道在Java中分为基本数据类型和引用数据类型。那么 ==在这两个类型中作用是不一样的。

  • 基本数据类型:比较的是 ==两边值是否相等

  • 引用数据类型:比较的是 ==两边内存地址是否相等

基本数据类型包括: byteshortcharintlongfloatdoubleboolean

而通过Java文档中的 equals()方法描述,所有要实现自己的 equals()方法都要遵守下面几个规则

  • 自反性:对于任何对象x, x.equals(x)应该返回 true

  • 对称性:对于任何两个对象x和y,如果 x.equals(y)返回 true,那么 y.equals(x)也应该返回 true

  • 传递性:对于多个对象x,y,z,如果 x.equals(y)返回 truey.equals(z)返回 true,那么 y.equals(z)也应该返回 true

  • 一致性:对于两个非空对象x,y,在没有修改此对象的前提下,多次调用返回的结果应该相同

  • 对于任何非空的对象x, x.equals(null)都应该返回 false

hashCode方法

Object中的 hashCode()方法是一个本地方法,返回一个 int类型的哈希值。

public native int hashCode();

在 hashCode()方法中也有一些规约

  • 如果对象在使用 equals方法中进行比较的参数没有修改,那么多次调用一个对象的 hashCode()方法返回的哈希值应该是相同的。

  • 如果两个对象通过 equals方法比较是相等的,那么要求这两个对象的 hashCode方法返回的值也应该是相等的。

  • 如果两个对象通过 equals方法比较是不同的,那么也不要求这两个对象的 hashCode方法返回的值是相同的。但是我们应该知道对于不同对象产生不同的哈希值对于哈希表(HashMap等等)能够提高性能。

equals方法和hashCode方法会在哪用到

这两个方法经常出现在Java中的哪个类里面呢?如果看过 HashMap源码的应该了解这两个方法经常出现在 HashMap中。网上介绍 HashMap类的文章有很多了,这里就简单介绍一下 HashMap

当一个节点中的链表超过了8的时候就会变为红黑树,以解决链表长度过长以后查询速度慢的缺点。

57e4285c3456cdd330db06930d772abe.png

HashMap是由数组和链表组成的高效存储数据的结构。那么是如何确定一个数据存储在数组中的哪个位置呢?就是通过 hashCode方法进行计算出存储在哪个位置,还记得我们上面讲 hashCode方法说了有可能两个不同对象的 hashCode方法返回的值相同,那么此时就会产生冲突,产生冲突的话就会调用 equals方法进行比对,如果不同,那么就将其加入链表尾部,如果相同就替换原数据。

计算位置当然不是上面简单的一个 hashCode方法就计算出来,中间还有一些其他的步骤,这里可以简单的认为是 hashCode确定了位置。

什么时候去覆盖这两个方法呢?

如果你不将自定义的类定义为 HashMap的key值的话,那么我们重写了 equals方法而没有重写 hashCode方法,编译器不会报任何错,在运行时也不会抛任何异常。

如果你想将自定义的类定义为 HashMap的key值得话,那么如果重写了 equals 方法那么就必须也重写 hashCode方法。

接下来我们可以看一下我们使用自定义的类作为 HashMap的key,并且自定义的类不重写 equals和 hashCode方法会发生什么。

自定义的类

@Builder

@NoArgsConstructor

@AllArgsConstructor

class CustomizedKey{

private Integer id;

private String name;

}

接下来我们看使用自定义的类作为key

public static void main(String[] args) {

Map<CustomizedKey, Integer> data = getData();

CustomizedKey key = CustomizedKey.builder().id(1).name("key").build();

Integer integer = data.get(key);

System.out.printf(String.valueOf(integer));

}

private static Map<CustomizedKey,Integer> getData(){

Map<CustomizedKey,Integer> customizedKeyIntegerMap = new HashMap<>();

CustomizedKey key = CustomizedKey.builder().id(1).name("key").build();

customizedKeyIntegerMap.put(key,10);

return customizedKeyIntegerMap;

}

我们可以看到程序最后打印的是一个 null值。原因正如上面我们说的一样。

  • hashCode:用来计算该对象放入数组中的哪个位置,因为是两个都是new的对象,所以即使里面的值一样,但是对象所处的地址却不同,所以使用默认的 hashCode也就不同,当然在 hashMap中就不会认为两个是一个对象。

接下来我们就重写一下这两个方法。如果我们使用 IDEA的话,那么直接使用快捷键即可。

0226ded8d7e7b0b13ea514bdd9837ca8.png

接下来我们看我们实现的两个方法

@Builder

@NoArgsConstructor

@AllArgsConstructor

class CustomizedKey{

private Integer id;

private String name;

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

CustomizedKey that = (CustomizedKey) o;

return Objects.equals(id, that.id) &&

Objects.equals(name, that.name);

}

@Override

public int hashCode() {

return Objects.hash(id, name);

}

}

然后我们再次运行上面的程序发现输出打印已经变成了 10

我们也能够使用 Lombock提供的 @EqualsAndHashCode注解简化代码

代码地址:https://github.com/modouxiansheng/Doraemon


(完)

MarkerHub文章索引:

https://github.com/MarkerHub/JavaIndex

【推荐阅读】

知乎问答:搞开发就怕加班还学不到东西?

很全很牛逼,看完这篇Elasticsearch实战,我觉得我可以写个百度~

基于Jwt资源无状态认证权限管理系统bootshiro

别用Date了,Java8新特性之日期处理,现在学会也不迟!

eblog项目讲解视频上线啦,长达17个小时!!

e8211e91bfd3eebc5cc142d90f5d44b6.png

好文章!点个在看!

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

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

相关文章

ssh客户端_一款基于TAS框架的SSH客户端蠕虫

TEA是一款基于TAS框架的SSH客户端蠕虫&#xff0c;从本质上说&#xff0c;它是一个仿冒的SSH客户端&#xff0c;它能够修改tty输入/输出来实现任意命令执行&#xff0c;或通过SSH连接来上传自身以实现渗透感染。为了实现该工具的正常功能&#xff0c;远程主机需要满足以下条件&…

分享到系统面板_win7电脑没有nvidia控制面板怎么办【解决方法】

我们在使用电脑的时候&#xff0c;当电脑显卡出现问题导致屏幕画面不清晰时&#xff0c;可以使用win7系统自带nvidia控制面板&#xff0c;它能够对显卡进行设置&#xff0c;提升显卡功能&#xff0c;不过很多电脑用户点击nvidia控制面板时却提示nvidia显示设置不可用&#xff0…

day3-文件操作之基本操作

一、文件的基本操作 文件内容&#xff1a; Somehow, it seems the love I knew was always the most destructive kind 不知为何&#xff0c;我经历的爱情总是最具毁灭性的的那种 Yesterday when I was young 昨日当我年少轻狂1、read() 当read()函数中传入整数(int)参数&#…

spad 探测器_从光到光子—“单光子”探测器

光电探测器光电探测器是指在光辐射作用下将其非传导电荷变为传导电荷的一类器件。在电子学中&#xff0c;二极管是一种具有不对称传输特性的双端电子元件&#xff0c;在一个方向上对电流具有低(理想为零)电阻&#xff0c;在另一个方向上具有高(理想为无限)电阻。最常见的类型如…

天地图专题五:在天地图上绘制电子区域并保存数据

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请注明出处。 上一文章讲了如何在天地图上显示坐标轨迹。 本文介绍如何在天地图上绘制电子区域&#xff08;电子范围或电子栅栏&#xff09;&#xff0c;并且&#xff0c;我们要将我们绘制的电子区域的坐标数据保存到数…

微信和支付宝的服务器在哪里,手机恢复出厂设置,里面支付宝与微信怎么办?原来数据在这里...

当手机使用一段时间之后&#xff0c;因为硬件落后会出现卡顿、内存不足等情况&#xff0c;这个时候提高手机速度最直接的一个办法就是恢复出厂设置&#xff0c;虽然不能从根源上解决问题&#xff0c;但是还是可以凑合个半年时间的。那么这个时候就出现一个问题&#xff0c;手机…

mysql insert 不需要日志_MySQL数据库性能优化(1)「转」

1、MySQL概述从本文开始我们将讨论建立在块存储方案之上的关系型数据库的性能优化方案和集群方案。关系型数据库的选型将以创业公司、互联网行业使用最广泛的MySQL数据为目标&#xff0c;但是MySQL的安装过程和基本使用方法等知识并不在我们讨论的范围内。后续几篇文章我们首先…

Java swing中的keyListener使用事例

最近在学习Java swing&#xff0c;写了一个域内聊天室&#xff0c;实现用户登录ip,端口号之后&#xff0c;进入聊天窗口聊天&#xff1a; 通过菜单条增加了几个功能&#xff0c;边框&#xff0c;字体&#xff0c;颜色和文件传输。风格里的样式都可以通过自己选择来设置。 介绍以…

「前端」History API与浏览器历史堆栈管理

本文由尚妆前端开发工程师欲休撰写 本文发表于尚妆博客&#xff0c;欢迎订阅&#xff01; 移动端开发在某些场景中有着特殊需求&#xff0c;如为了提高用户体验和加快响应速度&#xff0c;常常在部分工程采用SPA架构。传统的单页应用基于url的hash值进行路由&#xff0c;这种实…

Andrew Ng机器学习(一):线性回归

1.什么是线性回归&#xff1f; 用线性关系去拟合输入和输出。 设输入为x&#xff0c;则输出yaxb。 对于多元的情况yb1a1x1a2x2...anxn。 用θ表示系数&#xff0c;可以写作&#xff1a; 其中&#xff0c;x01。 2.线性回归有什么用&#xff1f; 对于连续输入和输出的问题&#x…

ICMP(Internet Control Message Protocol)网际控制报文协议初识

ICMP是&#xff08;Internet Control Message Protocol&#xff09;Internet控制报文协议。它是TCP/IP协议族的一个子协议&#xff0c;用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用…

oracle 删除主键_大数据量删除的思考 4

译者 汤健 沃趣科技数据库技术专家出品 沃趣科技在本系列的前一期文章中&#xff0c;我制作了一些图&#xff0c;突出显示了按表扫描执行大量删除操作和按索引范围扫描执行大量删除之间的主要区别。根据所涉及的数据模式&#xff0c;选择正确的策略可能对随机I/Os的数量、生…

redis 持久化 + 主从复制+ 集群

2019独角兽企业重金招聘Python工程师标准>>> 一、 Linux 下的 Redis 安装 && 启动 && 关闭 && 卸载 http://blog.csdn.net/zgf19930504/article/details/51850594 注&#xff1a;设置 redis.conf bind***.***.*.(127.0.0.1) redis启动&…

怎么运行c语言_C语言 原来是这样调用硬件的

大家都知道我们可以使用C语言写一段程序来控制硬件工作&#xff0c;但你知道其工作原理吗&#xff1f;网友北极C语言在实际运行中&#xff0c;都是以汇编指令的方式运行的&#xff0c;由编译器把C语言编译成汇编指令&#xff0c;CPU直接执行汇编指令。所以这个问题就变成&#…

更新和插入的并发问题_mysql经典面试题:如何读写分离?主从原理是啥?同步的延时问题...

面试题你有没有做 MySQL 读写分离&#xff1f;如何实现 MySQL 的读写分离&#xff1f;MySQL 主从复制原理的是啥&#xff1f;如何解决 MySQL 主从同步的延时问题&#xff1f;考点分析高并发这个阶段&#xff0c;肯定是需要做读写分离的&#xff0c;啥意思&#xff1f;因为实际上…

maven建立webapp项目时显示Cannot change version of project facet Dynamic web module to 2.5

为什么80%的码农都做不了架构师&#xff1f;>>> 网上查了很多东西都没啥用&#xff0c;其实直接把这段代码加到web.xml头部&#xff0c;自然就不报错了 <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns:xsi"http://www.…

HTTPS 原理解析

http://www.cnblogs.com/zery/p/5164795.html 一 前言 在说HTTPS之前先说说什么是HTTP&#xff0c;HTTP就是我们平时浏览网页时候使用的一种协议。HTTP协议传输的数据都是未加密的&#xff0c;也就是明文的&#xff0c;因此使用HTTP协议传输隐私信息非常不安全。为了保证这些隐…

kbmmw 5.0 中的REST 服务

目前关于REST 服务的话题越来越热&#xff0c;kbmmw 在5.0 里面开始支持rest。今天我就试一下kbmmw 的 rest 服务。闲话少说&#xff0c;开始。 老规矩&#xff0c;放上两个kbmMWServer1和 kbmMWHTTPSysServerTransport1两个控件。 设置kbmMWHTTPSysServerTransport1的server 属…

多租户saas 架构_[译/注] Force.com 多租户互联网应用开发平台的设计

原文地址 http://cloud.pubs.dbs.uni-leipzig.de/sites/cloud.pubs.dbs.uni-leipzig.de/files/p889-weissman-1.pdf译注&#xff1a;原文发表于 ACM&#xff0c;2009年6月作者Craig D Weissman, CTO, Salesforce.comSteve Bobrowski, Technical Marketing Consultant, Salesfor…

富文本

View Code转载于:https://www.cnblogs.com/baidaye/p/5295448.html