Java之父【Object】的面试知识点总结 hashcode equals ==

== 和 equals()的区别

== :对于基本类型和引用类型的作用效果是不同的

  1. 基本类型:==比较的是值
  2. 引用类型:==比较的是对象的内存地址

equals:不能用于判断基本数据类型的变量,只能用来判断两个对象是否相等,equals方法存在两种使用情况

  1. 类没有重写equals()方法:通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象,使用的默认是 Object类equals()方法
  2. 类重写了equals()方法:一般我们都重写 equals()方法来比较两个对象中的属性是否相等;若它们的属性相等,则返回 true(即,认为这两个对象相等)

String 中的 equals 方法是被重写过的,因为 Object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值
当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象

String a = new String("ab"); // a 为一个引用
String b = new String("ab"); // b为另一个引用,对象的内容一样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
System.out.println(aa == bb);// true
System.out.println(a == b);// false
System.out.println(a.equals(b));// true
System.out.println(42 == 42.0);// true

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;
}

hashCode()方法

image.png
hashCode() 的作用是获取哈希码(int 整数),也称为散列码
散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)
HashSet如何检查重复

  • 当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashCode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashCode 值作比较,如果没有相符的 hashCode,HashSet 会假设对象没有重复出现。但是如果发现有相同 hashCode 值的对象,这时会调用 equals() 方法来检查 hashCode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度

为什么两个对象有相同的 hashCode 值,它们也不一定是相等的

  • 因为 hashCode() 所使用的哈希算法也许刚好会让多个对象传回相同的哈希值。越糟糕的哈希算法越容易碰撞(所谓哈希碰撞也就是指的是不同的对象得到相同的 hashCode )如果两个对象的hashCode 值相等,那这两个对象不一定相等(哈希碰撞)。如果两个对象的hashCode 值相等并且equals()方法也返回 true,我们才认为这两个对象相等。如果两个对象的hashCode 值不相等,我们就可以直接认为这两个对象不相等

为什么重写equals()时必须重写hashCode()方法

  • 如果重写 equals() 时没有重写 hashCode() 方法的话就可能会导致 equals 方法判断是相等的两个对象,hashCode 值却不相等

1. equals()方法和hashCode()方法的联系

1.1 equals()方法

equals()方法用于比较两个对象是否相等。默认情况下,equals()方法比较的是对象的引用地址,即判断两个对象是否指向内存中的同一地址。然而,很多情况下我们需要自定义对象的相等性判断逻辑,例如判断对象的内容是否相等。因此,我们可以在类中重写equals()方法,实现自定义的对象比较逻辑。

1.2 hashCode()方法

hashCode()方法用于计算对象的哈希码(散列码)。哈希码是一个整数,用于快速地在哈希表等数据结构中查找对象。在Java中,哈希表的实现如HashMap和HashSet等就是基于哈希码来进行快速查找的。默认情况下,hashCode()方法返回的是对象的内存地址的整数表示。同样地,我们也可以在类中重写hashCode()方法,自定义对象的哈希码计算逻辑。

2. equals()、hashCode()和集合类的关系

在Java中,很多集合类如HashMap、HashSet等在内部使用了哈希表来存储数据。在使用这些集合类时,如果要正确地判断对象是否相等,就需要同时重写equals()和hashCode()方法。

2.1 equals()方法的影响

如果我们重写了equals()方法来定义对象相等的规则,那么在集合类中判断两个对象是否相等时就会使用这个规则。

2.2 hashCode()方法的影响

在将对象放入哈希表中时,哈希表会根据对象的哈希码来确定存储的位置。因此,如果两个对象被判断为相等(根据equals()方法),那么它们的哈希码应该相等。即使两个对象的内容相同,但如果它们的哈希码不相等,哈希表会认为它们是不同的对象。
为了保证哈希表的正确性,我们需要确保以下关系成立:

  1. 如果两个对象相等,那么它们的哈希码必须相等。
  2. 如果两个对象的哈希码相等,它们不一定相等。
3. 示例:重写equals()和hashCode()

下面是一个示例,展示了如何在自定义类中重写equals()和hashCode()方法:

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

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

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

    public static void main(String[] args) {
        Person person1 = new Person("Alice", 25);
        Person person2 = new Person("Bob", 30);

        Map<Person, String> personMap = new HashMap<>();
        personMap.put(person1, "Person 1 Data");
        personMap.put(person2, "Person 2 Data");

        System.out.println(personMap.get(person1)); // 输出:Person 1 Data
        System.out.println(personMap.get(person2)); // 输出:Person 2 Data
    }
}

在上述示例中,我们重写了equals()方法来根据name和age判断两个Person对象是否相等,同时也重写了hashCode()方法以保证相等的对象具有相同的哈希码。在使用HashMap存储Person对象时,可以正常地根据对象的内容进行查找和存储。

结论

equals()和hashCode()`是Java编程中非常重要的方法,它们在对象比较和哈希码计算方面发挥着关键作用。通过正确地重写这两个方法,我们可以在集合类中正常地进行对象的存储和检索操作,保证程序的正确性和性能。同时,了解了这两个方法的关系,也能更好地理解Java中的集合类和对象操作。

  • 有没有可能两个不相等的对象有相同的 hashcode?

有可能,两个不相等的对象可能会有相同的 hashcode 值,这就是为什么在 hashmap 中会有冲突。相等 hashcode 值的规定只是说如果两个对象相等,必须有相同的hashcode 值,但是没有关于不相等对象的任何规定。

  • 两个相同的对象会有不同的 hash code 吗?

不能,根据 hash code 的规定,这是不可能的

  • 31
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值