关于equals()方法,jdk源码给出如下五点建议,你知道哪些?

【1.JDK底层源码剖析】5.2为什么等值判断用 compareTo()而不用equals() 在数值类型(如BigDecimal、BigInteger)的比较中,推荐使用compareTo()而非equals()。核心区别在于:equals()要求对象完全一致(包括精度和结构),而compareTo()仅比较数值大小。例如,BigDecimal("2.0")和BigDecimal("2.00")用equals()比较会返回false,但用compareTo()会认为数值相等。这种差异源于equals()会检查精度等附加属性,而compareTo()会临时对齐精 阅读详情

一、趣谈

(1)面试题

  • 面试官:“你知道equals和==有什么区别吗?”
  • 我的心理活动:这不是送分题吗?今早上刚背过,我要回答的有逼格一点,这样我就可以获得面试官的认可,得到这份工作,在不久的将来就会出任CEO,迎娶白富美,走向人生巅峰。
  • 面试官:"喂,你知道吗?"
  • 我:“不好意思面试官,刚才在总结思路。关于这个问题,我是阅读过jdk源码的,equals是比较对象内容,==是比较对象地址。”
  • 面试官:“你确定吗?你看的那部分源码?”
  • 我:“。。。。。。”
  • 面试官:“好了,你回去等通知吧。”

(2)一些思考

关于上面的面试题,我相信很多小伙伴会脱口而出,equals比内容,==比地址。那么真实情况是什么呢?让我们看看jdk源码来分析这个问题。

没错,这就是Object(the root of the class hierarchy)中equals()方法的源码,仅仅是使用"=="来判断。那么有为什么会有equals方法比较内容这一说法呢。究其根本是因为java的多态机制,我们的jdk中帮我们重写了一些类的equals方法(封装类,String等),所以看起来好像equals方法是比较内容一样。当我们使用自定义对象时,我们调用equals方法很明显是比较两个对象的地址。如果我们也想比较内容那么就要重写equals方法。

二、JDK源码中的建议

(1)equals()的使用

我们重写equals方法大部分是因为要将自定义bean作为HashMap的key时。 我们接下来看看HashMap中常用的几个用到equals()的地方。

1. boolean containsKey(Object key);

containsKey(Object key)


public boolean containsKey(Object key) {
        return getNode(hash(key), key) != null;
    }

hash(Object key)

//根据对象的hashCode()方法返回一个int
 static final int hash(Object key) {
        int h;
        //可以从这里看出,HashMap允许key为null。
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

getNode(int hash, Object key)

这段代码Josh Bloch(超级牛,感兴趣可以百度,可以说没有他,就没有这么优秀的作品)是作者之一,他的风格一向如此,喜欢在逻辑运算符上赋值,所以初看可能比较费劲。 注意看红框里的都是赋值操作,然后用赋的值本身去做逻辑运算。 我们可以看到判断一个key是否存在,(去掉一些边界判断) 首先查看hash()值是否相等,然后查看对象是否地址相同(即同一个对象)或调用equals()查看是否相等。

2.V get(Object key);

    public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

可以看到这个调用了刚才上面的代码。

3.public V put(K key, V value) ;

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

可以看到如出一辙的风范,这里的代码我们仅指出此次我们研究的重点步骤。

  • 查看集合是否为空,如果为空开始扩容,然后new一个节点插入该集合。
  • 查看给定key的hash()位置(HashMap是一个数组,每个元素放置在tab[(length - 1) & hash]位置,如果该位置已有元素则通过链表或树继续添加)是否有元素,如果没有new一个节点放入该位置。
  • 如果该位置已经存在元素,则查看该位置的key值和要插入的key值是不是同一个对象(首先判断hash()值,然后判断是否是同一个对象即看==返回值,或者equals()方法返回true),因为null==null,所以可以看出HashMap中只允许一个键为null。如果是同一个对象更新value值,如果不是进行遍历(链表或树),直到找到同一个key值,更新value,或者插入新节点(k,v)。

我们总结一下,在HashMap中很多时候用到了判断两个key是否相等。他们的规则如下:

  • 如果hashCode()不同,两个对象不同(所以说如果我们要重写equals()方法来自定义两个对象是否相等,必须要重写hashCode()方法,因为首先判断的是hash值。)
  • 如果hashCode()相同,再查看==||equals(),如果==||equals()返回true则表示是同一个对象。

(2)equals()重写的五点建议

/**
     * Indicates whether some other object is "equal to" this one.
     * <p>
     * The {@code equals} method implements an equivalence relation
     * on non-null object references:
     * <ul>
     * <li>It is <i>reflexive</i>: for any non-null reference value
     *     {@code x}, {@code x.equals(x)} should return
     *     {@code true}.
     * <li>It is <i>symmetric</i>: for any non-null reference values
     *     {@code x} and {@code y}, {@code x.equals(y)}
     *     should return {@code true} if and only if
     *     {@code y.equals(x)} returns {@code true}.
     * <li>It is <i>transitive</i>: for any non-null reference values
     *     {@code x}, {@code y}, and {@code z}, if
     *     {@code x.equals(y)} returns {@code true} and
     *     {@code y.equals(z)} returns {@code true}, then
     *     {@code x.equals(z)} should return {@code true}.
     * <li>It is <i>consistent</i>: for any non-null reference values
     *     {@code x} and {@code y}, multiple invocations of
     *     {@code x.equals(y)} consistently return {@code true}
     *     or consistently return {@code false}, provided no
     *     information used in {@code equals} comparisons on the
     *     objects is modified.
     * <li>For any non-null reference value {@code x},
     *     {@code x.equals(null)} should return {@code false}.
     * </ul>
     * <p>
     * The {@code equals} method for class {@code Object} implements
     * the most discriminating possible equivalence relation on objects;
     * that is, for any non-null reference values {@code x} and
     * {@code y}, this method returns {@code true} if and only
     * if {@code x} and {@code y} refer to the same object
     * ({@code x == y} has the value {@code true}).
     * <p>
     * Note that it is generally necessary to override the {@code hashCode}
     * method whenever this method is overridden, so as to maintain the
     * general contract for the {@code hashCode} method, which states
     * that equal objects must have equal hash codes.
     *
     * @param   obj   the reference object with which to compare.
     * @return  {@code true} if this object is the same as the obj
     *          argument; {@code false} otherwise.
     * @see     #hashCode()
     * @see     java.util.HashMap
     */
    public boolean equals(Object obj) {
        return (this == obj);
    }

在注释上使用ctrl+shifgt+空格,就会出现文档注释预览(idea2020版本做了更好的优化)

这个方法用来指示另一个对象是否"equals to"本对象。该方法实现对非空对象引用的一个等价关系:

  • 反身性: 对于任意非空引用x,x.quals(x)应该返回true。
  • 对称性:对于任意非空引用值{x}和{y} , x.equals(y)应返回true当且仅当y.equals(x)返回true 。
  • 传递性:对于任意非空引用值x , y ,和z ,如果x.equals(y)返回true和y.equals(z)返回true ,那么x.equals(z)应该返回true 。
  • 一致性:对于任意非空引用值x和y ,如果没有修改equals()方法中设置的信息。多次调用x.equals(y)应该始终返回true或始终返回false ,对于任意非空引用x,x.equals(null)应该返回false 。

请注意,每当重写hashCode方法时,通常都需要重写该方法,以便维护hashCode方法的一般约定,该约定声明相等的对象必须具有相等的hash代码。

三、JDK源码中的优秀示例

(1)String

 public boolean equals(Object anObject) {
 		//如果地址相同,直接返回true
        if (this == anObject) {
            return true;
        }
        //判断是否是String的实例(值得注意的是null不是任何对象的实例,也就是说如果传入参数为null,直接返回false)
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            //首先查看长度是否相同
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                //逐一判断字符
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;
		//根据字符的unicode值,以31为基生成hashCode
        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

(2)自定义bean模仿

class Student {
    private String name;

    public Student(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o instanceof Student) {
            Student student = (Student) o;
            if (student.name != null && student.name.equals(name)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }
}
OpenClaw 最强技能 self-improving-agent 详解:让 AI 从错误中自主学习 self-improving-agent 是 OpenClaw 生态中最受欢迎的技能插件,下载量突破 268k。它能让 AI 记住犯过的错误和解决方案,实现持续自我改进。本文深入讲解其工作原理、安装配置和实战案例。测试数据显示:部署流程时间从 15 分钟降到 2 分钟(87%↓),API 调试时间从 2 小时降到 20 分钟,数据库查询编写时间减少 90%。文章包含完整架构图、配置文件示例、3 个详细实战案例和性能测试数据,适合开发者、运维和数据分析师使用。 阅读详情

相关推荐

5G NR 双连接与载波聚合:PCell、SCell、PScell、SpCell 角色全解析

本文全面解析了5G NR中双连接与载波聚合技术的关键概念,详细介绍了PCell、SCell、PScell和SpCell的角色与功能。通过实际案例和配置示例,帮助读者理解这些小区在提升网络覆盖和速率方面的作用,以及在实际组网中的优化策略。

weixin_33220360的博客 376

equals方法详解

一、equale方法是什么? Object 类中的 equals 方法是用于检测一个对象是否等于另外一个对象。在Object类中实现的 equals 方法将确定两个对象是否具有相同的引用(内存地址)。如果两个对象具有相同的引用,那么他们一定是相等的,看看下面这段代码的运行: public static void main(String[] args) { Object o = new Object(); //分别将 o 赋值给变量o1,o2 Object o1 ...

qq_57887050的博客 3万+

Spring Cloud 整合(一) CRUD

Springcloud 整合之 CRUDSpringcloud介绍功能概述为什么要选用Springcloud Springcloud介绍 功能概述 实现微服务 Spring Cloud为开发人员提供了工具,以快速构建分布式系统中的某些常见模式(例如,配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,群集状态)。分布式系统的协调导致样板式样,并且使用Spring Cloud开发人员可以快速站起来实现这些样板的服务和应用程序。 为什么要选用Springcloud

Kerwin-Lin的博客 1501

equals ( ) 方法详解

equals详解 、equals与== 的区别

m0_59751050的博客 1万+

生态学家都在用的MixSIAR:用R语言搞定稳定同位素混合模型(从数据整理到结果解读)

本文详细介绍了生态学家常用的MixSIAR工具,通过R语言实现稳定同位素混合模型分析,从数据整理到结果解读全流程。文章涵盖环境准备、模型构建、参数设置、运行诊断及可视化等关键步骤,帮助研究者科学分析河口鱼类食物来源,适用于生态学研究和湿地保护政策制定。

weixin_28683065的博客 440

cmu15445 2023fall project4 详细过程(包括Bonus Tasks) Concurrency Control

CMU15-445 23fall project 4详解

LA的博客 1606

equals()方法详解

一、equals方法作用: equals()方法是用来判断其他的对象是否和该对象相等 二、equals()方法在object类中定义: public boolean equals(Object obj) { return (this == obj); } 上边我们很明显看出是比较2个对象引用地址是否相同,但是我们平时在调用String、Integer等封装类型时的eq...

乔瑞的博客 2万+

OPC UA 服务端的模拟工具及客户端工具

详细介绍如何使用 Prosys OPC UA Simulation Server 作为 OPC UA 服务端的模拟工具来生成数据模型,并使用 Softing OPC UA Client 作为客户端工具,直观地查看和验证模拟生成的数据。

weixin_44462773的博客 9889

Java中的equals方法详解:比较方法

如果不覆盖equals方法,则调用该方法时会使用继承的Object类的实现,这种默认实现无法提供正确的比较行为,因为它无法知道哪些属性或状态在两个对象中是必须相同的。在这个例子中,a和b是两个不同的Integer对象,虽然它们的值相同,但是它们指向的是不同的对象,因此使用==运算符比较时返回false。3)传递性:对于任何非null的引用值x、y和z,如果x.equals(y)返回true,y.equals(z)也返回true,那么x.equals(z)也应该返回true;

weixin_62458944的博客 1万+

XGBoost实战:从原理到调参,手把手教你提升模型性能(附Python代码)

本文深入解析XGBoost核心原理,并提供一套从数据准备、系统性调参到生产部署的完整实战指南。通过剖析目标函数、正则化项与分裂算法,帮助读者理解参数背后的数学逻辑,并利用交叉验证、早停法及自动化工具(如Optuna)高效提升模型性能。文中附有详尽的Python代码示例,涵盖类别特征处理、缺失值应对、不平衡数据调整及模型可视化等高级技巧。

weixin_29178069的博客 460

vue3 - 最新详细实现高德地图绘制动态热力图详细教程,在某区域或城市地图上做“热力图层“展示人流量、旅游人口密度、热量图、全国地区地理热力图,利用颜色的深浅表示密度或强度等场景(详细示例代码教程)

vue3,nuxt3,高德地图,热力图,绘制热力图层,人流量,vue3使用高德地图实现某个区域热力图,vue3高德地图api加载热力图及关闭,接收热力图数据并渲染热力图,关掉热力图,Vue使用高德API制作热力图,热力图加载不出来,电子围栏围住热力图,vue3中使用高德地图渲染热力图组件,高德地图使用热力图详细教程,报错,卡顿,出不来怎么办,无法关闭,怎么解决这个问题,出错,城市名称,城市某个街道,城区,省份,市区,县城,乡镇,村,各省份的热力图,交通流量,人口流量,密度,旅游出行,人口数量,颜色介绍,深浅

✅ 精选推荐文章 5207

Java中equals()方法的理解与使用

在Java中,`equals()`方法是用于比较两个对象是否相等的重要方法。它属于`Object`类的方法,因此所有的Java对象都继承了这个方法。但是,`Object`类中的`equals()`方法默认实现是比较两个对象的引用是否相同,即它们是否指向内存中的同一个对象。在实际开发中,我们往往需要根据对象的实际内容来判断是否相等,这时就需要重写`equals()`方法。

qq_36720723的博客 7162

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

关于equals()方法,jdk源码给出如下五点建议

关于上面的面试题,我相信很多小伙伴会脱口而出,equals比内容,==比地址。那么真实情况是什么呢?让我们看看jdk源码来分析这个问题。

Java新生代 2678

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

equals()方法总结

超类Object中有这个equals()方法,该方法主要用于比较两个对象是否相等。该方法的源码如下: public boolean equals(Object obj) { return (this == obj); } 我们知道所有的对象都拥有标识(内存地址)和状态(数据),同时“==”比较两个对象的的内存地址,所以说使用Object的equals()方法是...

weixin_30810583的博客 127

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【Java比较学习】重写equals方法的安全写法

重写equals方法的正确打开方式 正文开始@Assassin 目录:重写equals方法的正确打开方式1. 什么是equals方法?1.1 equals方法:2. 为什么要重写equals方法?2.1 举个例子吧~3. 分析equals源码:4. 正确重写equals方法: 1. 什么是equals方法? 我们首先得知道,Object类是 Java中所有类的父类(超类/基类),也就是说,在Java中,所有的类都是默认继承自Object类的,换言之,Object类中所实现的方法我们都可以直接拿来用。而eq

NingHai's blog 2399

JDK源码阅读之Object

Object       JAVA中Object是所有类的超类,也就是说一切对象都是继承自Object类。我们从这里迈入JDK源码的大门。 Object中的方法一览 private static native void registerNatives(); public final native Class<?> getCla...

带翅膀的猫的博客 3653

重写hashCode()方法和equals()方法

一、前言 本篇文章主要探讨的问题有三个: 1、首先我们为什么需要重写hashCode()方法和equals()方法? 2、在什么情况下需要重写hashCode()方法和equals()方法? 3、如何重写这两个方法? 二、为什么需要重写hashCode()方法和equals()方法 首先,为什么要重写equals()方法。我们在定义类时,我们经常会希望两个不同对象的某些属性值相同时就认...

LinDongTian 2127

Java常见面试问题: equals()与hashCode()的使用

目录 1 equals()与‘==’的区别 2 equals()方法的重写规则 3 为什么重写equals()的同时还需要重写hashCode() 4 JDK 7中对hashCode()方法的改进 5 Java API文档中关于hashCode()方法的规定 6 重...

weixin_30335575的博客 233

java重写equals()方法和hashCode()方法

java重写equals()方法和hashCode()方法

Aaaaaaaaaaaaaaai的博客 1824

JDK 8 equals() & ==

equals() 是 java.lang.Object 的一个实例方法,被所有的子类所继承(可被复写)。 以下是 JDK 8 中 java.lang.Object.equals() 源码: 1 public boolean equals(Object obj) { 2 return (this == obj); 3 } 这个方法很简单,当自身和自...

diqiexie4777的博客 233

两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?

不对,两个对象的 hashCode()相同,equals()不一定 true。 首先先新建一个类来看一下重写equals和hashCode方法以后,jdk默认生成hashCode的源码 package com.ms.sso.utils; import lombok.Data; import java.util.Objects; @Data public class MQTest ...

qq_35771266的博客 3万+

【Java源码】String中的equals方法

本文基于JDK1.8 1 String中equals源码分析 String是final类型,它不可被继承。String的equals方法如下所示: /** * Compares this string to the specified object. The result is {@code * true} if and only if the argument is...

It一zhai男 798

java Object类和equals()方法详解 == 和equals的区别

文章目录

码农回顾 3879

JDK源码之解读String最终类的equals()和hashcode()方法实现原理

JDK源码之解读String最终类的equals()和hashcode()方法实现原理 最近在看JDK源码,先从简单入手,比如 String类 ,List、Map和Set接口的实现类。。。 1,equals(). “abd”.equals(“abc”)采取的是两字符串长度相等,在相等情况下,分别赋值给两字节数组,循环数组,如对应位置两数组值不相等,则return fals

qq_17280849的博客 759

【Java源码JDK1.8】equals()和==的区别?

一、equals()和==的区别 ==是基本运算符,可以比较8种基本类型,用来比较对象的引用是否指向同一块内存地址。 equals()是一个方法,不可以对8种基本类型进行比较,见源码1,它默认的方法中也使用了==,比较的也是对象的地址。见源码2,只不过equals()可以对其进行重写,像String、Date、Math、File、包装类等大部分类都重写了Object的equals()方法。重写后...

徐明晓的博客 538
上一篇: 消息队列——经典5连问——你能抗几道?
下一篇: Spring框架中都用到了哪些设计模式?
Javaesandyou
博客等级 码龄5年 742粉丝 563原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值