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;远程主机需要满足以下条件&…

Selenium入门11 滚动条控制(通过js)

这一节要有js基础。做web端的UI自动化必须要有html&#xff0c;css&#xff0c;javascript前端基础。 滚动条控制&#xff1a; 1 移动垂直滚动条 document.documentElement.scrollTop 2 移动垂直滚动条 document.documentElement.scrollLeft 3 找到某个元素&#xff0c;移动到可…

Qt之QNetworkInterface

简述 QNetworkInterface类负责提供主机的IP地址和网络接口的列表。 QNetworkInterface表示了当前程序正在运行时与主机绑定的一个网络接口。每个网络接口可能包含0个或多个IP地址&#xff0c;每个IP地址都可选择性地与一个子网掩码和/或一个广播地址相关联。这样的列表可以通过…

第二周计划

上周计划回顾 3.5 ~ 3.11 数据&#xff1a; 评师网爬取&#xff0c;完成&#xff1a;2k条记录 finished后端 数据结构 技术选型 学校API封装未完成&#xff1a;后端负责人出差 工作暂停产品 功能设计&#xff1a;主要功能提交&#xff1a;原型图 几个页面 每个页面大概功能完成…

python编程软件排行榜_PYPL 9月编程语言排行榜发布 Python一枝独秀

开发者可以将 PYPL 作为一个参考&#xff0c;决定学习何种语言或 IDE&#xff0c;或者在新的软件项目中使用何种语言或数据库。9 月份的榜单如下&#xff1a;前五名分别是 Python、Java、JavaScript、C# 与 PHP。相比去年 9 月份的数据&#xff0c;除了 Python 大幅上涨了 4.5%…

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

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

Python之数据加密与解密(hashlib、hmac、random、base64、pycrypto)--转载

本文内容 数据加密概述Python中实现数据加密的模块简介hashlib与hmac模块介绍random与secrets模块介绍base64模块介绍pycrypto模块介绍总结参考文档提示&#xff1a; Python 2.7中的str是字节串&#xff0c;而Python 3.x中的str是字符串。本文中的代码都是通过Python 2.7实现的…

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)参数&#…

QT连接多种数据库f方法及测试

QT提供了对多种数据库的访问支持&#xff0c;对SQL Server也可以通过ODBC来进行访问。要想顺利访问SQL Server。 首先要保证以下几点&#xff1a;1. QT编译时已经编译了QtSql2. 编译了ODBC插件。可以通过 configure -plugin-sql-odbc来保证&#xff0c;也可以单独编译~/src/plu…

服务器如何实现电脑无线桥接,无线路由器WDS桥接成功副路由器下电脑无法上网怎么办【解决方法】...

摘 要无线WDS桥接设置完成后&#xff0c;在副路由器管理面&#xff0c;运行状态 无线状态 中&#xff0c;WDS状态显示成功&#xff0c;但电脑通过副路由无法上网。该问题可能与主、副路由器的设置有关&#xff0c;如下图所示&#xff1a; 解决办法&#xff1a; 排查一&#xff…

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

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

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

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

Mysql中natural join和inner join的区别

假设有如下两个表TableA&#xff0c;TableB TableA TableB Column1 Column2 Column1 Column3 1 2 1 3TableA的Column1列名和TableB的Column1列名相同。 SELECT * FROM TableA INNER JOIN TableB USING (Column1) SEL…

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

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

python线上编辑问题_python django - static文件处理与线上部署测试

static文件相关操作涉及&#xff1a;a. 文件位置与访问路径映射b. setting.py与static相关配置STATIC_URLSTATIC_ROOTSTATICFILES_DIRSc. html中对于static文件引用方式d. python manage.py collectstatic1. 开发环境-目录结构2. setting.py 设置STATIC_URL /static/# STATIC_…

android arcgis 绘制圆_arcgis for android 定位 圆

不多说直接代码 &#xff0c;群里人共享的方法一&#xff1a; /*** 绘制圆,配合 cleargraphicLayer()清除** param center 圆心* param radius 半径* param alpha 填充的透明度 0-100* param fillColor 填充的颜色*/public void DrawCircle(Point center, double radius, int a…

CreateSolidBrush

[声明] WINGDIAPI HBRUSH WINAPI CreateSolidBrush(COLORREF color); [功能] 初始化一个指定颜色的画刷。画笔可以随后被选为任何设备上下文的当前刷子。 [参数表] color 画刷的颜色[返回值] Long&#xff0c;如函数执行成功&#xff0c;就返回指向新画笔的一个句柄&#xff1b…

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

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

javascript面试题以及对所涉及到的知识点的总结

前言 这几天将js方面的知识系统的回顾了一遍&#xff0c;但是当尝试去做一些面试题时觉得解决问题的能力以及效率还是有所欠缺&#xff0c;在这里特意记录一下所做的面试题并总结所涉及到的相关知识点。 一、面试题、答案以及总结 1、截取字符串abcdefg的efg var str"abcd…

十代主板改win7_技嘉B460主板UEFI+GPT装win7|10代CPU装win7 Bios设置

随着英特尔十代酷睿处理器的全面上市,针对主流用户的B460平台成为了大众主要关注的目标。作为国际一线板卡品牌的技嘉科技针对十代酷睿的特点,推出了B460主板。这块主板装win7、win10都可以,但是在装win7的过程中USB设备不能使用(本站支持最新的B460/Z490等新主板驱动),需要…