java中的==、equals和hashCode以及hashCode生成

2023-05-16

转载自:( 点击打开链接)
  • 前言

    java中==、equals()、hashCode()都和对象的比较有关,在java中这三者各有什么用处呢,即java中为什么需要设计这三种对象的比较方法呢?

  1. 关于==

        ==是容易理解的。java设计java就是要比较两个对象是不是同一个对象。

        对于引用变量而言,比较的时候两个引用变量引用的是不是同一个对象,即比较的是两个引用中存储的对象地址是不是一样的。

        对于基本数据类型而言,比较的就是两个数据是不是相等,没什么歧义。

        由于对于基本数据类型而言,没有方法,所以不存在equal()和hashCode()的问题,下面的讨论都是针对引用类型而言的。

  2. 关于equals()

    为什么java会设计equals()方法?

        ==比较的是两个对象是否是同一个对象,这并不能满足很多需求。有时候当两个对象不==的时候,我们仍然会认为两者是“相等”的,比如对于String对象,当两个对象的字符串序列是一直的,我们就认为他们是“相等”的。对于这样的需求,需要equals()来实现。对于有这种需求的对象的类,重写其equals()方法便可,具体的“相等”逻辑可以根据需要自己定义。

    需要注意的地方

        Object中equals()的默认实现是比较两个对象是不是==,即其和==的效果是相同的。

       java提供的某些类已经重写了equals()方法。自己写的类,如果需要实现自己的“相等”逻辑,需要重写equals()方法。

       

  3. 关于hashCode()

    为什么会设计hashCode()方法?

       hashCode()方法返回的就是一个数值,我们称之为hashCode吧。从方法的名称上就可以看出,其目的是生成一个hash码。hash码的主要用途就是在对对象进行散列的时候作为key输入,据此很容易推断出,我们需要每个对象的hash码尽可能不同,这样才能保证散列的存取性能。事实上,Object类提供的默认实现确实保证每个对象的hash码不同(在对象的内存地址基础上经过特定算法返回一个hash码)。

        分析到这个地方,看似没什么问题,三者的作用很清晰,好像他们之间也没什么关系。在java的规范上,hashCode()方法和equals()方法确实可以没有关系。

        但是!!!!!!!!有一个问题。

        问题如下:对于集合类HashSet、HashMap等和hash有关的类(以HashSet为例),是通过hash算法来散列对象的。对HashSet而言,存入对象的流程为:根据对象的hash码,经过hash算法,找到对象应该存放的位置,如果该位置为空,则将对象存入该位置;如果该位置不为空,则使用equals()比较该位置的对象和将要入的对象,如果两个相等,则不再插入,如果不相等,根据hash冲突解决算法将对象插入其他位置。

       而java规定对于HashSet判断是不是重复对象就是通过equals() 方法来完成,这就需要在两个对象equals()方法相等的时候,hash码一定相等(即hashCode()返回的值相等)。假设两个对象equals()方法相等的时候,hash码不相等,会出现equals()相等的两个对象都插入了HashSet中,这时不允许的。从而我们有了一下的结论:

        结论:对于equals()相等的两个对象,其hashCode()返回的值一定相等

       通过上面的分析,对于这个结论是没有异议的。结合前面关于hash码要尽可能不同的要求,现在变成了对于equals()相等的对象hash码要一定相等,而对于equals()不同的对象要尽量做到hash码不同。那么怎么才能保证这一点呢?

  4. 重写hashCode()

    首先,如何保证“对于equals()相等的对象hash码要一定相等”。

        equals()方法中对于对象的比较是通过比较对象中全部或者部分字段来完成的,这些字段集合记为集合A,如果我们计算hash码的时候,如果只是从集合A中选取部分字段或者全部字段来完成便可,因为输入相同,不管经过什么算法,输出一定相同(在方法中调用随机函数?这属于吃饱了撑的!)。如此设计便保证满足了第一个要求。

    其次,对于equals()不同的对象要尽量做到hash码不同。

        对于这一点的保证就是在设计一个好的算法,让不同的输入尽可能产生不同的输出。

       下面就详细介绍一下如何设计这个算法。这个算法是有现成的参考的,算法的具体步骤就是:

    [1]把某个非零常数值(一般取素数),例如17,保存在int变量result中;

    [2]对于对象中每一个关键域f(指equals方法中考虑的每一个域):

       [2.1]boolean型,计算(f ? 0 : 1);

       [2.2]byte,char,short型,计算(int)f;

       [2.3]long型,计算(int) (f ^ (f>>>32));

       [2.4]float型,计算Float.floatToIntBits(afloat);

       [2.5]double型,计算Double.doubleToLongBits(adouble)得到一个long,再执行[2.3];

       [2.6]对象引用,递归调用它的hashCode方法;

       [2.7]数组域,对其中每个元素调用它的hashCode方法。

    [3]将上面计算得到的散列码保存到int变量c,然后执行 result=37*result+c;

    [4]返回result。

    其实其思路就是:先去一个基数,然后对于equals()中考虑的每一个域,先转换成整数,再执行result=37*result+c;


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java中的==、equals和hashCode以及hashCode生成 的相关文章

随机推荐

  • PHP单文件上传的过程化函数封装

    提交文件的页面 xff1a upload php lt doctype html gt lt html lang 61 34 en 34 gt lt head gt lt meta charset 61 34 UTF 8 34 gt lt
  • PHP的单个文件上传、多个单文件上传、多文件上传

    单文件上传 upload1 php lt doctype html gt lt html lang 61 34 en 34 gt lt head gt lt meta charset 61 34 UTF 8 34 gt lt title g
  • PHP实现单文件上传、多个单文件上传、多文件上传的过程化封装

    上回提到 PHP的单个文件上传 多个单文件上传 多文件上传 这里给出 三种方式的统一实现 下面先给出各种方式的文件提交页面 xff1a 单个文件上传 upload1 php lt doctype html gt lt html lang 6
  • PHP的单文件上传类

    提交单文件的页面 upload php lt doctype html gt lt html lang 61 34 en 34 gt lt head gt lt meta charset 61 34 UTF 8 34 gt lt title
  • PHP的多文件上传类

    提交表单的页面 upload php lt doctype html gt lt html lang 61 34 en 34 gt lt head gt lt meta charset 61 34 UTF 8 34 gt lt title
  • Nginx负载均衡配置实例详解

    转载自 xff1a http www php100 com html program nginx 2013 0905 5525 html 负载均衡是我们大流量网站要做的一个东西 xff0c 下面我来给大家介绍在Nginx服务器上进行负载均衡
  • 基于Bootstrap使用jQuery实现简单可编辑表格

    editTable js 提供编辑表格当前行 添加一行 删除当前行的操作 xff0c 其中可以设置参数 xff0c 如 xff1a operatePos 用于设置放置操作的列 xff0c 从0开始 xff0c 1表示以最后一列作为放置操作的
  • ThinkPHP 大D方法思想下的JDBC操作数据库D类

    这里我封装出来的D 类 xff0c 是根据 ThinkPHP 中的 D 方法中做出来的 xff0c 其中有些出入的地方 xff0c 我进行了一些个性化的修正 xff0c 如 xff1a ThinkPHP 中操作数据库时 xff0c 需要在配
  • 基于MVC设计模式实现简单PHP框架(雏形)-初期

    xff08 记住 xff1a 这里只是提供思考的过程 xff09 其实这里只是一个我们课的Web实验 课程设计题目统计系统 xff0c 在做实验的过程中起初只是想往MVC靠拢而已 xff0c 却不知不觉地 实现 了基于MVC的简单框架的雏形
  • Rocketmq入门介绍

    目录 一 Rocketmq优势 二 Rocketmq与其他MQ对比 三 MQ基本概念 四 RocketMQ的4个组件 五 集群部署结构 工作流程 xff1a 模块功能特性 xff1a Nameserver Broker 生产者 Produc
  • 我的简单PHP框架——LabPHP

    就我上次提到的 基于MVC设计模式实现简单PHP框架 xff08 雏形 xff09 初期 这次列出我实现的LabPHP简易框架 xff0c 该框架中没有使用任何的模板引擎 xff0c 所以说要在模板中使用到php变量的话 xff0c 仍然需
  • 我的LabPHP框架的Demo应用——课程设计题目统计系统

    1 界面制作 xff08 为了方便起见 xff0c 这里我采用了Bootstrap 框架制作界面 xff09 xff1b 2 数据库设计 xff0c 正确创建students 表 xff1b admin表 xff1a 3 项目目录结构如下
  • 基于Bootstrap使用jQuery实现输入框组input-group的添加与删除

    注意这里要求使用到Bootstrap框架的输入框组 xff0c 如 xff1a lt div class 61 34 row 34 gt lt div class 61 34 col lg 6 34 gt lt div class 61 3
  • 网页中时光轴的简单实现

    时光轴效果如下 xff1a 鼠标滑过当前项时 xff0c 左侧图标大小变大 xff1a index html lt DOCTYPE html gt lt html lang 61 34 en 34 gt lt head gt lt meta
  • 伸缩自如的时光轴实现

    上回说到简单时间轴的实现 xff0c 这一次针对上回的实现的时光轴 xff0c 增加时光轴收起的功能 为了方便重用 xff0c 我分离css样式和js 使用过程中主要注意一下尽量使用css定义的时光轴样式即可 时光轴收起功能的实现过程可以查
  • 伸缩自如的时光轴实现——改进版

    上回讲到的是时光轴 伸缩自如 的实现 xff0c 如果基于响应式制作的话 xff0c 可能存在着许多潜在的BUG 如 xff1a 窗口变化时 xff0c 时光轴的 收起 和 展开 xff0c 都发生了一些变形 为此 xff0c 对原来的 t
  • 伸缩自如的时光轴实现_样式改版

    针对前几篇文章中实现的 伸缩自如 的时光轴 xff0c 对时光轴的样式进行又一次修改 xff0c 效果如下 xff1a 点击 收起 后 xff1a 修改后的 timeline css xff0c 如下 xff1a vertical time
  • ThinkPHP中的create方法与自动令牌验证

    转载自 xff1a Thinkphp中Create方法深入探究 ThinkPHP中的create方法与自动令牌验证实例教程 Thinkphp中Create方法深入探究 由于工作原因在thinkPHP的create 方法上遇到了问题 xff0
  • web安全之token和CSRF攻击

    上文我转载了两篇关于ThinkPHP令牌验证的文章 xff08 ThinkPHP中的create方法与自动令牌验证 xff09 其中提及到了 token xff0c 这里针对 token 的作用 xff0c 转载了另外两篇文章 xff08
  • java中的==、equals和hashCode以及hashCode生成

    转载自 xff1a xff08 点击打开链接 xff09 前言 java中 61 61 equals hashCode 都和对象的比较有关 xff0c 在java中这三者各有什么用处呢 xff0c 即java中为什么需要设计这三种对象的比较