首页 > 其他分享 >equals ,hashcode ,== ,三者之间的关系与区别

equals ,hashcode ,== ,三者之间的关系与区别

时间:2024-08-31 20:53:01浏览次数:14  
标签:相等 name 对象 equals hashCode Person hashcode 三者

为什么要重写 equals 和hashcode

        在Java中,重写equals方法和hashCode方法是为了确保对象在逻辑上相等时,它们在集合(如HashMapHashSet)中的行为也是一致的。

以下是详细解释:

为什么要重写 equals 方法

  1. 默认行为:默认情况下,Object类的equals方法比较的是两个对象的引用是否相同,即它们是否是同一个实例。这在大多数情况下并不符合我们的需求,因为我们通常需要比较对象的内容是否相等。
  2. 逻辑相等:在实际开发中,我们经常需要根据对象的某些属性(如ID、名称等)来判断两个对象是否相等。因此,我们需要重写equals方法,以便根据这些属性进行比较。

为什么要重写 hashCode 方法

  1. 集合框架的要求:Java的集合框架(如HashMapHashSet)依赖于hashCode方法来确定对象的存储位置。如果两个对象在逻辑上相等(即equals方法返回true),那么它们的hashCode值也必须相同。
  2. 性能优化hashCode方法的主要作用是提供一个快速的初步判断,以减少需要调用equals方法的次数。如果两个对象的hashCode不同,那么它们肯定不相等,无需进一步比较。

具体例子

假设我们有一个Person类,我们希望根据nameage属性来判断两个Person对象是否相等:

public class Person {
    private String name;
    private int age;

    // Constructor, getters, and setters

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

        在这个例子中,我们重写了equals方法,以便根据nameage属性来判断两个Person对象是否相等。同时,我们也重写了hashCode方法,以确保逻辑上相等的对象具有相同的hashCode值。

        重写equals方法和hashCode方法是为了确保对象在逻辑上相等时,它们在集合中的行为也是一致的。具体来说,这不仅符合业务逻辑需求,还能提高集合操作的性能。如果不重写这两个方法,可能会导致集合操作出现意外的结果。

  • 重写equals方法:确保逻辑上相等的对象在比较时返回true
  • 重写hashCode方法:确保逻辑上相等的对象具有相同的hashCode值,以满足集合框架的要求。

通过这种方式,我们可以确保对象在集合中的行为符合预期,避免出现逻辑错误和性能问题。

先比较hashcode,还是先比较equals

        在Java中,当需要判断两个对象是否相等时,通常会先比较它们的hashCode,然后再比较它们的equals方法。这种顺序的设计是为了提高比较的效率和准确性。

比较顺序

  1. 先比较 hashCode

    • 如果两个对象的hashCode不同,那么它们肯定不相等,无需进一步调用equals方法。
    • 这是因为hashCode是一个快速的初步判断,可以在大多数情况下迅速排除不相等的对象,从而提高性能。
  2. 再比较 equals

    • 如果两个对象的hashCode相同,那么它们可能相等,也可能不相等。此时需要进一步调用equals方法进行详细的比较。
    • equals方法会根据对象的属性进行详细的比较,以确定它们是否在逻辑上相等。

 还是用上面的pesron类作为示例

public class Person {
    private String name;
    private int age;

    // Constructor, getters, and setters

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

在这个例子中,当我们需要判断两个Person对象是否相等时,系统会先调用它们的hashCode方法:

  • 如果两个对象的hashCode不同,那么它们肯定不相等,无需进一步调用equals方法。
  • 如果两个对象的hashCode相同,那么再调用equals方法进行详细的比较。

为什么这样设计

  1. 性能优化:通过先比较hashCode,可以在大多数情况下迅速排除不相等的对象,从而减少调用equals方法的次数,提高比较的效率。
  2. 一致性要求:根据Java的规范,如果两个对象的equals方法返回true,那么它们的hashCode必须相同。反之,如果两个对象的hashCode不同,那么它们的equals方法必须返回false。这种设计确保了对象在集合中的行为一致性。

        在Java中,判断两个对象是否相等的顺序是先比较它们的hashCode,再比较它们的equals方法。这种顺序的设计既考虑了性能优化,也确保了对象在集合中的一致性行为。

  • 先比较 hashCode:快速排除不相等的对象。
  • 再比较 equals:详细比较对象的属性,确定它们是否在逻辑上相等。

通过这种方式,我们可以高效且准确地判断两个对象是否相等

equals与 == 的区别

        在Java中,equals方法和==操作符用于比较对象,但它们有不同的用途和行为。理解它们的区别对于正确使用Java语言非常重要。

== 操作符

  1. 比较对象引用

    • == 操作符用于比较两个对象的引用(内存地址)是否相同。
    • 如果两个引用指向同一个对象,则返回true;否则返回false
  2. 基本数据类型

    • 对于基本数据类型(如intcharboolean等),== 操作符比较的是它们的值是否相等。

equals 方法

  1. 比较对象内容

    • equals 方法是Object类中的一个方法,默认情况下比较的是对象的引用(即与==操作符行为相同)。
    • 但是,大多数类会重写equals方法,以便根据对象的属性(内容)来判断它们是否相等。
  2. 自定义比较逻辑

    • 通过重写equals方法,可以定义对象在逻辑上相等的条件。例如,根据对象的某些属性(如ID、名称等)来判断它们是否相等。

示例

假设我们有一个Person类,我们希望根据nameage属性来判断两个Person对象是否相等:

public class Person {
    private String name;
    private int age;

    // Constructor, getters, and setters

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

在这个例子中:

  • == 操作符会比较两个Person对象的引用是否相同。
  • equals 方法会比较两个Person对象的nameage属性是否相等。

具体比较

Person p1 = new Person("Alice", 30);
Person p2 = new Person("Alice", 30);
Person p3 = p1;

// 使用 == 操作符
System.out.println(p1 == p2); // false,因为 p1 和 p2 是不同的对象
System.out.println(p1 == p3); // true,因为 p1 和 p3 是同一个对象

// 使用 equals 方法
System.out.println(p1.equals(p2)); // true,因为 p1 和 p2 的 name 和 age 相同
System.out.println(p1.equals(p3)); // true,因为 p1 和 p3 的 name 和 age 相同
  • == 操作符:比较对象的引用(内存地址)是否相同,适用于基本数据类型和对象引用。
  • equals 方法:默认情况下比较对象的引用,但通常会被重写以比较对象的内容(属性)是否相等。

总结

  1. 为什么要重写 equals 和 hashCode 方法

    • 重写 equals 方法:默认的 equals 方法比较对象引用,重写后可以根据对象的属性判断逻辑相等性。
    • 重写 hashCode 方法:Java集合框架依赖 hashCode 来优化对象存储和查找,确保逻辑相等的对象具有相同的 hashCode
  2. equals 和 hashCode 的比较顺序

    • 先比较 hashCode:快速排除不相等的对象,提高性能。
    • 再比较 equals:详细比较对象属性,确定逻辑相等性。
  3. equals 与 == 的区别

    • == 操作符:比较对象引用(内存地址)是否相同,适用于基本数据类型和对象引用。
    • equals 方法:默认比较对象引用,通常重写以比较对象的内容(属性)是否相等。

        equals相等的hashcode也一定相等,而hashcode相等的equals不一定相等,通过正确重写和使用 equals 和 hashCode 方法,可以确保对象在集合中的行为符合预期,提高代码的正确性和性能。

标签:相等,name,对象,equals,hashCode,Person,hashcode,三者
From: https://blog.csdn.net/Broken_x/article/details/141605971

相关文章

  • 一文说透 String 的 HashCode
    首先需要明确版本,不同版本的实现是不同的。JDK1.8以前底层的实现是char[]。publicinthashCode(){inth=hash;if(h==0&&value.length>0){charval[]=value;for(inti=0;i<value.length;i++){h=31*......
  • equals与hashCode关系梳理
    目录equals用法hashCode用法总结为什么一个类中需要两个比较方法为什么重写equals方法时必须同时重写hashCode方法?Reference这个并不是一个通用性编程问题,只属于在Java领域内专有问题。要做好心理准备,这是一个复杂类的问题,要解答这个问题,需要梳理清楚两个函数和其它类之间......
  • 通感算一体化:(二)深度解读通、感、算三者的内含与联系
    一、6G和5G的区别6G的理论速度更快,可以达到“每秒10Tbps(万亿比特)”,比5G快了1000倍;峰值速率从Gbit/s提升到Tbit/s,体验速率从Mbps提升到Gbit/s,空口时延从毫秒级提升到亚毫秒级,定位精度从m级提升到cm级,网络容量提升到5G的1,000倍,连接密度从1个/平方米提升到10~100个/平方......
  • 等保、关基、密评三者之间的关系
    原文链接:http://www.lnsm.gov.cn/lnsm/zcfg/zcjd/2024032708282690302/index.shtml   在《网络安全法》和《密码法》中都明确规定了对关键信息基础设施开展安全评估检测的要求,同时也指出了商用密码应用安全评估、关键信息基础设施安全检测评估与网络安全等级测评三者之间应该......
  • 时间分辨率、采样率与采样深度三者关系理解
    在脑成像研究中,分辨率和采样率是一个经常被提及的概念,但分辨率和采样率有时候容易混淆。除此之外,采样深度这个重要的概念却很少被提及。因此,本篇随笔主要内容是为阐述上述三者的概念以及相关联系。概念的明晰了解关系之前,首先需要明晰三者的定义概念,其中分辨率仅会说明时间分辨......
  • 朋友吐槽我为什么这么傻不在源生成器中用string.GetHashCode, 而要用一个不够优化的ha
    明明有更好的hash方法有位朋友对我吐槽前几天我列举的在源生成器的生成db映射实体的优化点提前生成部分hashcode进行比较所示代码publicstaticvoidGenerateReadTokens(thisIDataReaderreader,Span<int>s){for(inti=0;i<reader.FieldCount;i++){......
  • equals方法
    /*Object类中成员方法:publicbooleanequals(Objectobj)protectedvoidfinalize()是做垃圾回收的,不是立刻就做回收面试题:finalfinallyfinalize区别?protectedObjectclone()知识点:1、==比较,如果比较的基本......
  • java基础 之 重写equals时为什么要重写hashCode
    文章目录前言回答了解哈希hashCode()总结前言了解equals戳这里→java基础之equals和==的区别请记住这句话:两个对象相同,哈希码一定相同。哈希码相同,两个对象不一定相同。回答只重写equals()方法,不重写hashCode()方法:存在A.equals(B)为true,但是hashCode不......
  • 多态,抽象,接口,Object,Equals
    1.多态1.1编译时多态:在编译时就能够确定调用哪个方法​方法重载是编译时多态,在编译期根据参数的数据类型,个数以及次序来确定调用方法1.2运行时多态:只有在运行时才能确定调用哪个方法,主要指动态绑定来实现,动态绑定是程序运行时确定调用哪个方法的过程,他依赖于对......
  • String的equals方法的实现原理以及==跟equals的区别
    publicclassStringTest05{publicstaticvoidmain(String[]args){Strings1="hello";Strings2=newString("hello");System.out.println(s1==s2);System.out.println(s1.equals(s2));}}此代码......