==和equals、hashCode方法

==:对于基本类型变量,使用==比较的是两个变量的值是否相等。对于引用类型变量,使用==比较的是两个变量的引用是否相等,即比较两个引用(对象)在内存中的地址值是否相等。由于任意两个对象在内存中的地址值都不一样,所以通过==比较两个对象的值肯定不相等。

其实==都是对数值进行比较,对于基本数据类型,比较两个变量的值,对于引用数据类型,比较两个对象在堆内存中的地址值(用16进制表示的数字),所以,==属于数值比较。

equals()方法:equals方法的作用也是判断两个对象在内存中的地址值是否相等。equals方法是Object类中的方法,其源码如下所示:

public boolean equals(Object obj) {return (this == obj);
}

由equals方法的源码可知,Object类中equals方法的作用与==的作用是一样的,都是比较两个对象在内存中的地址值是否相等,即判断两个对象是不是同一个对象。为了比较两个对象的内容是否相同,可以重写equals方法,如String、Integer、Date类中都对equals方法进行了重写。重写equals()方法之后,就是比较两个对象的内容是否相等,若它们的内容相等,则返回true(即认为这两个对象相等),否则,返回false。

对于“请解释字符串比较之中“==”equals()的区别”这个问题,需要考虑到字符串已经将equals方法重写了。可以如下回答:==是比较两个字符串在堆内存中的地址值是否相等,equals方法是比较两个字符串的内容是否相等。

hashCode()方法:hashCode方法的作用是获取哈希码(也称为散列码,是一个int类型的整数),这个哈希码的作用是确定该对象在哈希表(散列表)中的索引位置。也就是说,hashCode()方法只有在散列表中才能发挥出其作用,在其它情况下几乎没什么作用。hashCode方法是Object类中的方法,返回的是对象在内存中的地址值(16进制表示的int类型的整数,占4个字节,32位二进制位)。由于任意两个对象在内存中的地址值都不一样,所以通过hashCode方法得到的int型整数也不一样。为了比较两个对象的内容是否相同,可以重写hashCode方法,如String类中重写的hashCode方法的源码如下所示:

public int hashCode() {
int h = hash;    //Default to 0     String类中的私有变量
//private final char value[];    String类中保存字符串内容的数组if (h == 0 && value.length > 0) {    char val[] = value;for (int i = 0; i < value.length; i++) {h = 31 * h + val[i];}hash = h;}return h;
}

String源码中使用private final char value[];保存字符串内容,因此String是不可变的。

由于hashCode()方法只有在散列表中才能发挥出其作用,所以看一下hashCode方法在散列表中的作用。在Java集合中底层使用散列表实现的类有HashMap,Hashtable,HashSet等。由于Set集合中不允许存放重复的元素,所以HashSet中也不允许存放重复的元素,如何保证HashSet中不保存重复的元素呢?就是通过hashCode和equals方法来实现的。在HashSet中,基本的操作都是有HashMap实现的,因为HashSet底层是用HashMap存储数据的。假设将某个元素存放到HashSet集合中,首先根据hashCode方法计算出该元素在HashSet集合中的索引位置(元素的哈希值与HashMap集合大小取模),判断该位置是否已经存在元素,如果该位置为空,就将元素添加进去,如果不为空,再用equals方法比较该元素与已存在元素是否相等,如果相等,则不添加,否则新建一个结点添加该元素。

此处对HashMap的知识点做一个简单的介绍:在jdk1.7及以前版本,HashMap底层是用数组和链表的形式实现的,数组中存放的是桶,桶中存放的是链表的头结点,链表是用来解决哈希冲突的。如果多个元素的哈希值相等,但通过equals方法得到的值不等,就会产生哈希冲突。将具有哈希冲突的多个元素存放在同一个桶中的链表中,新添加的元素作为链表的头结点,原来的头结点作为新头结点的下一个节点。

有的面试官会问到“equals方法与hashCode方法有什么区别”,由上面分析可知,equals方法默认是比较两个对象在内存中的地址值是否相等,即两个对象是不是同一个对象,而hashCode方法默认是获取对象在内存中的地址值,根本不是对两个对象进行比较,因此,这两个方法的功能都不一样,无可比性。不过,equals方法与hashCode方法有一定的关系。

在重写equals方法与hashCode方法时,需要满足如下约定:

1. 在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,则对该对象调用hashCode方法多次,它必须始终如一地返回同一个整数。

2. 如果两个对象根据equals(Object o)方法是相等的,则调用这两个对象中任一对象的hashCode方法必须产生相同的整数结果。

3. 如果两个对象根据equals(Object o)方法是不相等的,则调用这两个对象中任一个对象的hashCode方法,不要求产生不同的整数结果。但如果能不同,则可能提高散列表的性能。

即,如果两个对象根据equals方法判断相等,则根据hashCode方法得到的结果必须相同,如果根据hashCode方法得到的结果相同,则两个对象根据equals方法判断不一定相等。

在重写hashCode方法时,最好使用Objects的hash()方法,如Objects.hash(field1,field2)。

Objects的hash()和hashCode()比较,Objects的hash()方法源码如下所示:

public static int hash(Object... values) {return Arrays.hashCode(values);
}

这里调用Arrays类的hashCode()函数:

public static int hashCode(Object a[]) {if (a == null)return 0;int result = 1;for (Object element : a)result = 31 * result + (element == null ? 0 : element.hashCode());return result;
}

由此可知,Objects的hash()方法的作用是将接收到的所有属性的哈希值进行组合。

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

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

相关文章

DAIN-SQL,DAIL-SQL,C3-SQL和 DIN-SQL 技术的理解和异同点

DAIN-SQL、DAIL-SQL、C3-SQL 和 DIN-SQL 都是自然语言处理&#xff08;NLP&#xff09;领域中&#xff0c;将自然语言问题转换为SQL查询语句&#xff08;Text-to-SQL&#xff09;的技术。以下是它们的解释和异同点&#xff1a; DAIN-SQL&#xff1a; DAIN-SQL是一种将复杂的Tex…

高效视频制作大提速,视频剪辑软件的高级自定义命令功能批量调整视频的色调、饱和度和亮度,轻松驾驭视频编辑技巧

在浩瀚的数字海洋中&#xff0c;视频如同璀璨的星辰&#xff0c;而每一颗星辰都渴望被精心雕琢&#xff0c;闪耀出最独特的光芒。想象一下&#xff0c;你手握一把神奇的钥匙&#xff0c;能够轻松解锁批量视频剪辑的奥秘&#xff0c;让每一帧画面都跃动着你的创意与激情。这把钥…

[RootersCTF2019]ImgXweb

审题 看到robots.txt,看到里面的文件&#xff0c;打开看到 you-will-never-guess这个字符串 进行注册登录 可以看到典型的jwt加密的Cookie 想到之前的字符串可能是密匙&#xff0c;更改为admin&#xff0c;进行登录。 成功后可以看到flag.png。 发现图形打不开 使用curl进…

ThreeJS创建一个3D物体的基本流程

1.创建场景&#xff1a;创建一个THREE.Scene实例&#xff0c;它将作为所有3D对象的容器。 // 创建场景 const scene new THREE.Scene(); 2.创建相机&#xff1a;创建一个相机对象&#xff0c;通常是THREE.PerspectiveCamera&#xff0c;用于定义观察场景的视角和位置。 //创…

32单片机HAL库的引脚初始化

在使用HAL库时&#xff0c;GPIO初始化函数定义在stm32f4xx_hal_gpio.c文件中&#xff0c;如下&#xff1a; void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init); 由这个函数可以看出&#xff0c;在初始化GPIO时&#xff0c;需要向函数传入2个结构体&…

解决QT打包发布App Store时(90135)错误

Asset validation failed (90135) Invalid bundle. The executable couldn’t be re-signed for upload to App Store Connect. The app may have been built or signed with unsupported or prerelease tools. (ID: 247c9a37-cef9-432a-9cc9-ca7caf261f08) 解决方法&#xff…

ubuntu【桌面】 配置NAT模式固定IP

DHCP分配导致虚拟机IP老变&#xff0c;SSH老要重新配置&#xff0c;设成静态方便些 一、设NAT模式 1、设为NAT模式 2、看模式对应的虚拟网卡 - VMnet8 3、共享主机网卡网络到虚拟网卡 - VMnet8 二、为虚拟网卡设置静态IP 记住这个IP 三、设置ubuntu固定IP 1、关闭DHCP并…

确保企业架构与业务的一致性与合规性:数字化转型中的关键要素与战略实施

在现代企业的数字化转型过程中&#xff0c;确保企业架构&#xff08;Enterprise Architecture, EA&#xff09;与企业业务的紧密一致性与合规性至关重要。无论是在战略层面还是运营层面&#xff0c;EA都为企业的未来发展提供了清晰的蓝图&#xff0c;确保企业在应对复杂的业务环…

Pinctrl子需要中client端使用pinctrl过程的驱动分析

往期内容 本专栏往期内容&#xff1a; Pinctrl子系统和其主要结构体引入Pinctrl子系统pinctrl_desc结构体进一步介绍Pinctrl子系统中client端设备树相关数据结构介绍和解析inctrl子系统中Pincontroller构造过程驱动分析&#xff1a;imx_pinctrl_soc_info结构体 input子系统专栏…

Failed to search for file: Cannot update read-only repo

今天在读《Linux就该这么学》并上机操作RedHat Linux 8。结果在执行指令时却出现了问题: 我明明已经是root权限了&#xff0c;我于是上网去找&#xff0c;但也没看到合适的解答。为什么会和书上的操作结果不一样。 后来我突然意识到是不是我打了不该打的空格&#xff0c;于是…

MQL实验(三)视图与游标

1.建立计算机系学生的视图student_cs,视图中包含sno&#xff0c;sname,dept,sex&#xff0c;totalcredit。使用select命令显示视图中的数据。 create view student_cs as select student.sno,sname,dept,sex,totalcredit from student where dept计算机; select * from stud…

SpringBoot实现验证码案例

目录 实现逻辑前后端交互接口前端代码后端代码 实现逻辑 1、后端功能&#xff1a;随机生成验证码图片&#xff0c;并把交给前端、接收用户输入&#xff0c;验证用户输入的验证码是否正确、 2、前端功能&#xff1a;显示验证码&#xff0c;提供输入框供用户输入他们看到的验证…

OpenCV基本操作(python开发)——(7)实现图像校正

OpenCV基本操作&#xff08;python开发&#xff09;——&#xff08;1&#xff09; 读取图像、保存图像 OpenCV基本操作&#xff08;python开发&#xff09;——&#xff08;2&#xff09;图像色彩操作 OpenCV基本操作&#xff08;python开发&#xff09;——&#xff08;3&…

记录新建wordpress站的实践踩坑:wordpress 上传源码新建站因权限问题导致无法访问、配置新站建站向导以及插件主题上传配置的解决办法

官方文档&#xff1a;How to install WordPress – Advanced Administration Handbook | Developer.WordPress.org 但是没写权限问题&#xff0c;可以下载到 wordpress官方包。 把下载的wordpresscn的包解压并上传到服务器目录下&#xff0c;但是因为是root上传导致了权限问题…

前端的全栈Deno篇(五):与前端保持一致的模块化方案,摆脱ERR_REQUIRE_ESM和mjs、cjs等模块混乱带来的心智负担

在现代JavaScript开发中&#xff0c;模块化系统的演变经历了多次变革&#xff0c;使得前端和后端开发人员在选择模块加载方式时常常感到困惑。尤其是Node.js所采用的CommonJS和ESM&#xff08;ECMAScript Modules&#xff09;两种模块体系&#xff0c;以及文件扩展名的多样性&a…

qt QBrush详解

1、概述 QBrush是Qt框架中的一个基本图形对象类&#xff0c;它主要用于定义图形的填充模式。QBrush可以用于填充如矩形、椭圆形、多边形等形状&#xff0c;也可以用于绘制背景等。通过QBrush&#xff0c;可以设置填充的颜色、样式&#xff08;如实心、渐变、纹理等&#xff09…

练习LabVIEW第三十四题

学习目标&#xff1a; 刚学了LabVIEW&#xff0c;在网上找了些题&#xff0c;练习一下LabVIEW&#xff0c;有不对不好不足的地方欢迎指正&#xff01; 第三十四题&#xff1a; 在一个波形表中显示三条随机数组成的曲线&#xff0c;分别用红&#xff0c;绿&#xff0c;蓝三种…

YOLOv11改进策略【卷积层】| CVPR-2020 Strip Pooling 空间池化模块 处理不规则形状的对象 含二次创新

一、本文介绍 本文记录的是利用Strip Pooling模块优化YOLOv11的目标检测网络模型。Strip Pooling结合了长而窄的卷积核形状在一个空间维度上的长程关系捕捉能力和在另一个空间维度上的局部细节捕捉能力,有效地处理复杂的场景信息。这一机制通过采用 1 N 1N 1N或 N 1 N1 N1的…

Rust:Vec<u8> 与 [u8] 之间的转换

在 Rust 中&#xff0c;Vec<u8> 是一个动态数组&#xff0c;而 &[u8] 是一个指向字节切片的不可变引用。这两者之间经常需要进行转换&#xff0c;因为它们在处理字节数据时非常常见。 从 &[u8] 转换为 Vec<u8> 要将一个字节切片 &[u8] 转换为一个 Ve…

彻底理解链表(LinkedList)结构

目录 比较操作结构封装单向链表实现面试题 循环链表实现 双向链表实现 链表&#xff08;Linked List&#xff09;是一种线性数据结构&#xff0c;由一组节点&#xff08;Node&#xff09;组成&#xff0c;每个节点包含两个部分&#xff1a;数据域&#xff08;存储数据&#xff…