首页 > 编程语言 >(转)Java中equals和==、hashcode的区别

(转)Java中equals和==、hashcode的区别

时间:2024-01-30 15:01:06浏览次数:30  
标签:Java 对象 Object equals hashCode key hashcode 方法

https://www.cnblogs.com/lixuwu/p/5676207.html

https://www.cnblogs.com/lixuwu/p/10662234.html

https://timzhouyes.github.io/2020/02/27/Java%E7%89%B9%E7%A7%8D%E5%85%B5/

https://blog.csdn.net/a745233700/article/details/83186808

https://www.cnblogs.com/dolphin0520/p/3681042.html

一.hashCode方法的作用

  对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode。在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。

  为什么这么说呢?考虑一种情况,当向集合中插入对象时,如何判别在集合中是否已经存在该对象了?(注意:集合中不允许重复的元素存在)

  也许大多数人都会想到调用equals方法来逐个进行比较,这个方法确实可行。但是如果集合中已经存在一万条数据或者更多的数据,如果采用equals方法去逐一比较,效率必然是一个问题。此时hashCode方法的作用就体现出来了,当集合要添加新的对象时,

(1)先调用这个对象的hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值,

(2.1) 如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;

(2.2) 如果存在该hashcode值, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址

  所以这里存在一个冲突解决的问题,这样一来实际调用equals方法的次数就大大降低了,说通俗一点:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。下面这段代码是java.util.HashMap的中put方法的具体实现。

 1 public V put(K key, V value) {
 2         if (key == null)
 3             return putForNullKey(value);
 4         int hash = hash(key.hashCode());  //  hashCode()方法返回一个int数,在Object类中的默认实现是“将该对象的内部地址转换成一个整数返回”。 
 5         int i = indexFor(hash, table.length);
 6         for (Entry<K,V> e = table[i]; e != null; e = e.next) {
 7             Object k;
 8             if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
 9                 V oldValue = e.value;
10                 e.value = value;
11                 e.recordAccess(this);
12                 return oldValue;
13             }
14         }
15  
16         modCount++;
17         addEntry(hash, key, value, i);
18         return null;
19     }

 

  put方法是用来向HashMap中添加新的元素,从put方法的具体实现可知,会先调用hashCode方法得到该元素的hashCode值,然后查看table中是否存在该hashCode值,如果存在则调用equals方法重新确定是否存在该元素,如果存在,则更新value值,否则将新的元素添加到HashMap中。从这里可以看出,hashCode方法的存在是为了减少equals方法的调用次数,从而提高程序效率。

 

 

当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码

 ps:jdk文档中也是这么要求的。

下面是我查阅了相关资料之后对以上的说明做的归纳总结:

1.若重写了equals(Object obj)方法,则有必要重写hashCode()方法。

2.若两个对象equals(Object obj)返回true,则hashCode()有必要也返回相同的int数。  //  原因:一般一个类的对象如果会存储在HashTable,HashSet,HashMap等散列存储结构中,那么重写equals后最好也重写hashCode,否则会导致存储数据的不唯一性(存储了两个equals相等的数据)。而如果确定不会存储在这些散列结构中,则可以不重写hashCode。但是个人觉得还是重写比较好一点

3.若两个对象equals(Object obj)返回false,则hashCode()不一定返回不同的int数。

4.若两个对象hashCode()返回相同int数,则equals(Object obj)不一定返回true。

5.若两个对象hashCode()返回不同int数,则equals(Object obj)一定返回false。

6.同一对象在执行期间若已经存储在集合中,则不能修改影响hashCode值的相关信息,否则会导致内存泄露问题。

标签:Java,对象,Object,equals,hashCode,key,hashcode,方法
From: https://www.cnblogs.com/wxdlut/p/17997110

相关文章

  • Java连接kubernates集群最优雅的两种方式
    创建maven工程,pom.xml中引入连接k8s的客户端jar包:<properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><fabric.io.version>6.10.0</fabric.io.version></properties......
  • Java微服务框架开发
    Swagger常见问题:Swagger与高版本SpringBoot不兼容问题  分析源码查找问题解决springboot2.6和swagger冲突的四种方法解决方法:按如下配置修改策略,如仍然不需,需按照上述四种方法第四种添加Beanspring:mvc:path-match:matching-strategy:ant_p......
  • 初识Java
    Java特征和优势简单性面向对象可移植性高性能分布式动态性多线程安全性健壮性Java三大版本WriteOnce、RunAnywhereJavaSE:标准版(桌面程序,控制台开发...)JavaME:嵌入式开发(手机,小家电...)JavaEE:E企业级开发(Web端,服务器开发...)JDK、JRE、JVMJDK:JavaDevelopme......
  • 使用Java编写HTTP客户端和服务器:一场与网络的欢乐共舞
    你是否曾经想过,如果有一天你可以和网络对话,那会是怎样的场景?好消息,Java给了你这个机会!今天,我们要一起探讨如何使用Java编写HTTP客户端和服务器,让你和网络的互动变得更加有趣和欢乐。首先,我们需要了解HTTP是什么。简单来说,HTTP就是“超文本传输协议”,它就像是我们与网络交流的语言。......
  • 使用Java实现HTTPS通信:一场加密的探戈
    你知道吗,HTTPS不仅仅是一个简单的字母替换游戏,它是互联网安全的重要组成部分。好消息是,有了Java,我们也可以轻松地实现HTTPS通信!今天,就让我们一起跳进加密的探戈世界,了解如何使用Java实现HTTPS通信。首先,我们要明白HTTPS是什么。简单来说,HTTPS就是“超文本传输协议安全版”,它通过使......
  • 使用Java编写RESTful API:一场与HTTP的浪漫之舞
    下面是一个简单的示例,展示如何使用SpringBoot创建一个基本的RESTfulAPI:1. 创建一个新的SpringBoot项目。你可以使用SpringInitializr或任何你喜欢的IDE来创建项目。2. 3. 在pom.xml文件中添加SpringBootWebStarter依赖:4. xml复制代码<dependency> <groupId>org.springf......
  • Java实现基于清除后分配规则的垃圾回收器及其实现原理
    (Java实现基于清除后分配规则的垃圾回收器及其实现原理)实现基于清除后分配(mark-and-sweep)规则的垃圾回收器,可以按照以下步骤进行1.标记阶段(MarkingPhase)从根对象(如堆栈、全局变量)开始,递归地遍历所有可达的对象,并将其标记为活动对象,即不被回收的对象。这一过程可以使用深度优......
  • java运行时内存模型
    1.概述在虚拟机自动内存管理机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,不容易出现内存泄漏和内存溢出问题,看起来由虚拟机管理内存一切都很美好。不过,也正是因为Java程序员把控制内存的权力交给了Java虚拟机,一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟......
  • 使用Java处理HTTP状态码:一场代码与数字的奇妙之旅
    在互联网的世界里,HTTP状态码就如同交通信号灯,告诉我们请求是否成功,或者出了什么问题。当我们在Java中与Web服务器打交道时,了解这些状态码是必不可少的。今天,就让我们一起踏上这段代码与数字的奇妙之旅,看看如何使用Java来处理这些HTTP状态码。首先,我们要明白HTTP状态码的作用。简单......
  • 使用Java处理HTTP标头:一场头与头的较量
    在Web开发中,HTTP标头就像是一封邮件的信封,上面写满了关于邮件的重要信息。同样地,HTTP标头也包含了许多关于请求或响应的重要信息。那么,如何在Java中处理这些标头呢?今天,我们就来探讨一下这个话题,看看如何用Java来读取、修改和设置HTTP标头。首先,要处理HTTP标头,我们需要一个能够读取......