java为什么要重写hashCode和equals方法

如果不被重写(原生)的hashCode和equals是什么样的?
  1.       不被重写(原生)的hashCode值是根据内存地址换算出来的一个值。
  2.       不被重写(原生)的equals方法是严格判断一个对象是否相等的方法(object1 == object2)。
  为什么需要重写equals和hashCode方法?
      在我们的业务系统中判断对象时有时候需要的不是一种严格意义上的相等,而是一种业务上的对象相等。在这种情况下,原生的equals方法就不能满足我们的需求了
      所以这个时候我们需要重写equals方法,来满足我们的业务系统上的需求。那么为什么在重写equals方法的时候需要重写hashCode方法呢?
      我们先来看一下Object.hashCode的通用约定(摘自《Effective Java》第45页)
  1.     在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,那么,对该对象调用hashCode方法多次,它必须始终如一地返回 同一个整数。在同一个应用程序的多次执行过程中,这个整数可以不同,即这个应用程序这次执行返回的整数与下一次执行返回的整数可以不一致。
  2.     如果两个对象根据equals(Object)方法是相等的,那么调用这两个对象中任一个对象的hashCode方法必须产生同样的整数结果。
  3.   如果两个对象根据equals(Object)方法是不相等的,那么调用这两个对象中任一个对象的hashCode方法,不要求必须产生不同的整数结果。然而,程序员应该意识到这样的事实,对于不相等的对象产生截然不同的整数结果,有可能提高散列表(hash table)的性能。
     如果只重写了equals方法而没有重写hashCode方法的话,则会违反约定的第二条:相等的对象必须具有相等的散列码(hashCode)
     同时对于HashSet和HashMap这些基于散列值(hash)实现的类。
HashMap的底层处理机制是以数组的方法保存放入的数据的(Node<K,V>[] table),其中的关键是数组下标的处理。数组的下标是根据传入的元素hashCode方法的返回值再和特定的值异或决定的如果该数组位置上已经有放入的值了,且传入的键值相等则不处理,若不相等则覆盖原来的值,如果数组位置没有条目,则插入,并加入到相应的链表中。检查键是否存在也是根据hashCode值来确定的。所以如果不重写hashCode的话,可能导致HashSet、HashMap不能正常的运作、
  如果我们将某个自定义对象存到HashMap或者HashSet及其类似实现类中的时候,如果该对象的属性参与了hashCode的计算,那么就不能修改该对象参数hashCode计算的属性了。有可能会移除不了元素,导致内存泄漏。

  扩展:
      在重写equals方法的时候,需要遵守下面的通用约定:
           1、自反性。
               对于任意的引用值x,x.equals(x)一定为true。
           2、对称性。
               对于任意的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)也一定返回true。
           3、传递性。
               对于任意的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也一定返回true。
           4、一致性。
               对于任意的引用值x和y,如果用于equals比较的对象没有被修改的话,那么,对此调用x.equals(y)要么一致地返回true,要么一致的返回false。
           5、对于任意的非空引用值x,x.equals(null)一定返回false。
     重写hashCode方法的大致方式:
            a、把某个非零常数值,比如说17(最好是素数),保存在一个叫result的int类型的变量中。
            b、对于对象中每一个关键域f(值equals方法中考虑的每一个域),完成一些步骤:
                1、为该域计算int类型的散列吗c:
                    1)、如果该域是boolean类型,则计算(f?0:1)。
                    2)、如果该域是byte、char、short或者int类型,则计算(int)f。
                    3)、如果该域是float类型,则计算Float.floatToIntBits(f)。
                    4)、如果该域是long类型,则计算(int)(f ^ (f>>>32))。
                    5)、如果该域是double类型,则计算Double.doubleToLongBits(f)得到一个long类型的值,然后按照步骤4,对该long型值计算散列值。
                    6)、如果该域是一个对象引用,并且该类的equals方法通过递归调用equals的方式来比较这个域,则同样对这个域递归调用hashCode。如果要求一个更为复杂的比较,则为这个域计算一个“规范表示”,然后针对这个范式表示调用hashCode。如果这个域的值为null,则返回0(或者其他某个常数)
                    7)、如果该域是一个数组,则把每一个元素当做单独的域来处理。也就是说,递归地应用上述规则,对每个重要的元素计算一个散列码,然后根据步骤下面的做法把这些散列值组合起来。
                2、按照下面的公式,把步骤1中计算得到的散列码C组合到result中:
                    result = 31*result+c。
            c、返回result。
            d、写完hashCode方法之后,问自己“是否相等的实例具有相等的散列码”。如果不是的话,找出原因,并修改。
            可以通过org.apache.commons.lang.builder.HashCodeBuilder这个工具类来方便的重写hashCode方法。

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

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

相关文章

stl中map函数_map :: max_size()函数,以及C ++ STL中的Example

stl中map函数C STL映射:: max_size() (C STL map::max_size() ) It returns the maximum number of elements the container(map) is able to hold but at runtime, the size of the container may be limited to a value smaller than specified by max_size() by the amount…

arduino 蓝牙示例_Arduino简单实例之八_蓝牙模块

1) 说明&#xff1a;蓝牙模块用于和手机或其它带蓝牙的设备通讯。蓝牙设备分为主从两种模式&#xff0c;作为主设备时&#xff0c;它查找和连接其它设备&#xff1b;作为从设备时只能被只它设备连接&#xff1b;通讯模式分透明传输和AT命令模式。最好购买主从一体的蓝牙模…

zabbix使用JMX监控tomcat

JMX 全称是Java Management Extensions,即Java管理扩展。Java程序会开放一些端口&#xff0c;用来获取运行状况。 从Zabbix2.0开始&#xff0c;内置了监控JMX的功能,叫做"Zabbix Java Gateway ",在Zabbix Serve上会启动名为"Zabbix Java Gateway "的进程&…

自定义控件添加属性_|AutoCAD LT 2019 Mac自定义功能区的方法

AutoCAD LT是一款非常好用的CAD三维设计绘图软件&#xff0c;最新版本2019拥有改进的桌面、新应用实现跨设备工作流&#xff0c;以及DWG比较等新功能&#xff0c;并且AutoCAD LT 2019 Mac可以根据你的需要和工作习惯来自定义功能区&#xff0c;下面为大家带来自定义功能区的详细…

操作系统中的文件系统和访问方法

文件 (File) A file is basically a sequence of bytes organized into blocks that are understandable by any machines. In other words, the collection of related information that is stored in a secondary storage device is also called a file. The file is a colle…

centos7镜像加速_docker 镜像加速CentOS7详细介绍

前言在Docker Hub官网上注册帐号&#xff0c;即可下载使用仓库里的全部的docker镜像。而因为网络原因&#xff0c;国内的开发者没办法流畅的下载镜像&#xff0c;经常会出现下载中断的错误。解决方法就是使用国内的容器Hub加速服务&#xff0c;本质就是更改pull优先级较高的服务…

java 根据类名示例化类_Java LocalDateTime类| atOffset()方法与示例

java 根据类名示例化类LocalDateTime类atOffset()方法 (LocalDateTime Class atOffset() method) atOffset() method is available in java.time package. atOffset()方法在java.time包中可用。 atOffset() method is used to create an OffsetDateTime to merge this LocalDat…

Zabbix监控——proxy 分布式监控配置

proxy分布式监控 Zabbix proxy是在大规模分布式监控场景中&#xff0c;采用的一种用以分担server端压力的分层结构&#xff0c; proxy可以代替zabbix server检索客户端的数据&#xff0c;然后把数据汇报给zabbix server&#xff0c;极大的减轻了server的负载压力&#xff0c;使…

AutoCAD_acadiso.dwt卡死

2019独角兽企业重金招聘Python工程师标准>>> 问题描述&#xff1a;每次执行到打开acadiso.dwt就卡死&#xff0c;且电脑显示有网&#xff0c;确打不开网页 可能原因&#xff1a;可能是因为AotuCAD是盗版的 解决办法&#xff1a; 1.在任务管理器中把WSCommCntr.exe进…

else 策略模式去掉if_java – 用状态/策略模式替换if/else逻辑

我认为你应该使用GoF模式Chain of responsibility.你应该引入两个接口&#xff1a;1)你将检查正确条件的条件,例如“如果zip文件不存在”并返回布尔结果 – 如果条件满足则返回“true”,否则“else”,2)执行策略,它将运行分配有条件的动作,例如&#xff1a; “从指定的URL下载它…

docker简介与搭建

1 . 对docker的理解&#xff1a; Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间…

Java BigInteger类| toByteArray()方法与示例

BigInteger类testBit()方法 (BigInteger Class testBit() method) testBit() method is available in java.math package. testBit()方法在java.math包中可用。 testBit() method is used to convert this BigInteger to a byte [] that holds 2s complement denotation of thi…

007_Web to lead

转载于:https://www.cnblogs.com/bandariFang/p/6229491.html

设置header_Nginx的这些安全设置,你都知道吗?

Nginx 是最流行的 Web 服务器&#xff0c;可以只占用 2.5 MB 的内存&#xff0c;却可以轻松处理 1w 的 http 请求。做为网站的入口&#xff0c;Nginx 的安全设置重要性不言而喻。下面带你一起去认识一下这些安全配置吧&#xff01;nginx.conf是 Nginx 最主要的配置文件&#xf…

动态路由协议_动态路由协议的类别

动态路由协议Dynamic routing protocols have been divided into 2 categories i.e Distance vector protocols and Link state protocols. Both of these protocols are being explained in detail in this tutorial. 动态路由协议分为距离矢量协议和链路状态协议两大类 。 本…

docker镜像创建与优化

1 . 创建镜像 有两种方法构建镜像&#xff1a; docker commit &#xff1a;将运行的容器保存成镜像Dockerfile&#xff1a;自动构建 使用docker commit 创建镜像分为三步&#xff1a; 运行容器修改容器将容器保存为镜像 举例&#xff1a; [rootdocker ~]# docker load -i…

ISP运营商实验室测试机架拓扑搭建经验分享

大家好&#xff0c;有些日子没更新干货了&#xff0c;近期难得有假期进行修整&#xff0c;思前顾后还是坐下来聊聊自己长期负责维护和搭建的实验室环境。废话不多说&#xff0c;直接上图。因为图较大&#xff0c;分上下部分进行上传。网络主框架&#xff08;上&#xff09;服务…

关于二手交易用户指南怎么写_让用户拍案叫绝文案怎么写?试试这3个方法

“共鸣”到底是什么&#xff1f; 为什么有些文章会引起共鸣&#xff0c;而有些则没有。现在假设为产品家用手持式美容仪写一份副本。 由于主要重点是“家庭使用”&#xff0c;因此您立即想到了“家庭美容”的口号。 尽管这句话很简单易懂&#xff0c;但谈论起来总是很简单……似…

结构化程序goto语句_C ++ goto语句| 查找输出程序| 套装1

结构化程序goto语句Program 1: 程序1&#xff1a; #include <iostream>#include <math.h>using namespace std;int main(){int num1 1;int num2 0;MY_LABEL:num2 num1 * num1;cout << num2 << " ";num1 num1 pow(2, 0);if (num1 < …

docker仓库搭建、加密、用户认证

1 . 含义及理解&#xff1a; 仓库分为公开仓库&#xff08;Public&#xff09;和私有仓库&#xff08;Private&#xff09;两种形式。最大的公开仓库是 Docker Hub&#xff0c;存放了数量庞大的镜像供用户下载。 国内的公开仓库包括 Docker Pool等&#xff0c;可以提供大陆用户…