Java中==与equals的区别 + equals与hashcode的引申

目录

先说结论

解释

注:

equals比较的过程有两个实现思路

思路一:

思路二:

主流:第二种是目前的主流思路

hashCode

idea自动生成的equals和hashCode方法

hashCode什么时候用

equals中用不到hashCode(理由见equals比较的过程的两个实现思路)

比较器中一般也用不到hashCode

在HashSet与HashMap中常用hashCode


先说结论

== :对于基本类型比的是具体值,如int a=4;int b=5;那么比的就是具体值因为4<5,所以a不等于b。对于引用类型,==比的是地址

equals:在顶级父类Object中equals用的也是==,但是String等类系统已经重写过equals方法了,比的是其中的内容

解释

 基本类型存储可以通过一个地址进行存储,如int型,它可以通过一串二进制数进行存储,获取值的时候也是可以直接获取其内容,但是引用类型不能做到,比如String,他的底层是字符型数组,无法通过一次访问其地址得到所有值,所以==就比较的其地址,若是地址一样,则这两个对象必定相同

但是在日常使用我们肯定不能只通过地址去进行比较,因为有时候地址不同,但我们依然可以认为这两个对象相同,比如自定义一个学生类,如果两个对象的学号相同,我们就认为这两个学生对象相同,此时若是比较地址,这两个对象肯定不同,这时就需要通过内容去比较两。

我们最常用的比较内容的方法就是调用equals方法,但要注意,就像上面说的,在顶级父类Object中equals用的也是==,那为什么String类能通过.equals()比较其内容呢,就是因为Stringyi经重写过该方法了

这是Object类中的equals方法

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

这是String中重写的equals方法

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        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;
    }

可以看出,String先是比较了地址是否相同,地址若是相同,则两个对象必定相同,返回true,若不同则再比较其具体的元素。

注:

编写自定义类时,我们有时也需要重写equals方法和hashCode方法,这来两个一般是绑定的重写一个就要重写另一个

equals比较的过程有两个实现思路

思路一:

    先比较地址判断
    地址不同比较hash值,
    hash值相同再比较其中的具体元素是否相同

因为系统默认的hashCode,反回的是当前对象地址。我们需要返回其元素的hash值的和,这样才方便equals去判断。因为若两个对象相等,那么这两个对象一定有相同的哈希值;但若两个对象的哈希值相同,但这两个对象并不一定相等。如5=2+3但同时5=1+4;

思路二:

    先比较地址判断
    地址不同判断能否转化为同类,若是不能返回false,若能则强转为同类型
    之后比较其中的具体元素是否相同

主流:第二种是目前的主流思路

第一种方法中,首先比较地址,然后比较哈希值,最后再比较具体元素。这种实现方法在某些情况下可能会导致性能问题,因为如果两个对象的哈希值相同,但实际内容不同,那么仍然需要比较具体元素,这可能会导致额外的开销。

第二种方法中,先比较地址,然后判断能否转化为同类,若是不能直接返回false,若能则强转为同类型,然后再比较具体元素。这种方法更加通用,因为它考虑到了对象的类型转换,可以更好地处理继承关系和多态的情况。这种方法也更符合Java中equals方法的通用实现原则,即先比较引用,再比较类型,最后比较具体的内容。

因此,第二种方法更加通用和符合规范,也更容易适应不同的对象类型和继承关系,因此更为主流。

hashCode

hashCode()方法常被设计用来提高性能,其两者的关系在于:
①若两个对象相等(equals),那么这两个对象一定有相同的哈希值(hashCode);
②若两个对象的哈希值相同,但这两个对象并不一定相等。
 

idea自动生成的equals和hashCode方法

假设类中只有三个属性姓名(name)年龄(age)和学号(num)

idea重写的equals

public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name) && Objects.equals(num, student.num);
    }

idea自动重写的hashcode:

 1.
public int hashCode() {
        return Objects.hash(name, num, age);//将该类的所有值传入
    }
2.
调用Objects类的hash方法
 public static int hash(Object... values) {
        return Arrays.hashCode(values);
    }
3.
调用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;
    }

hashCode什么时候用

equals中用不到hashCode(理由见equals比较的过程的两个实现思路)

在重写equals()方法时,通常不需要直接使用重写的hashCode()方法。
  equals()方法用于比较两个对象的内容是否相等,而hashCode()方法用于计算对象的哈希码。
  然而,当你重写equals()方法时,通常也需要同时重写hashCode()方法,以确保一致性。如果两个对象在equals()方法中被认为是相等的,那么它们的hashCode()方法也应该返回相同的值。这是为了确保当对象被放入哈希表等数据结构时,它们的哈希码和相等性的定义是一致的。
  因此,虽然在重写equals()方法时不需要直接使用hashCode()方法,但是在实现类中通常需要同时重写hashCode()方法,以确保一致性。


比较器中一般也用不到hashCode

实现比较器的一般过程通常包括以下步骤:
          1.创建一个实现了Comparator接口的比较器类,或者使用匿名类或Lambda表达式实现比较器。
          2.在比较器类中重写compare方法,该方法定义了对象之间的比较规则。
         在这个过程中,并不需要直接使用hashCode()方法。
  hashCode()方法通常用于在哈希表等数据结构中存储对象,而比较器是用于定义对象之间的顺序关系的。
  然而,在某些情况下,你可能会在比较器中使用hashCode()方法来辅助比较对象。例如,如果你希望在比较器中实现一些复杂的逻辑,需要根据对象的哈希码进行比较,那么你可能会在比较器中使用hashCode()方法。
  总的来说,在实现比较器的一般过程中,并不需要直接使用hashCode()方法。不过,具体情况还是取决于你的需求和设计。


在HashSet与HashMap中常用hashCode

        hashCode()方法通常用于在哈希表等数据结构中存储对象。这些数据结构包括HashSet和HashMap等。在Java中,HashSet和HashMap都是基于哈希表实现的数据结构。
         在HashSet中,元素是无序的且不重复的。当你向HashSet中添加元素时,HashSet会使用元素的hashCode()方法来确定元素的存储位置,以及在检查元素是否重复时使用equals()方法。
          在HashMap中,元素是以键值对的形式存储的。在HashMap中,键的存储位置也是根据键的hashCode()方法来确定的。在检索键或存储键值对时,HashMap也会使用键的hashCode()方法和equals()方法来确定存储位置和检查键的相等性。
          因此,hashCode()方法在HashSet和HashMap等基于哈希表实现的数据结构中起着非常重要的作用,用于确定对象的存储位置和在检查相等性时的辅助作用。

  简单来说就是:在hash集合类中hashCode决定存储位置,equals判断是否存在相同数据

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值