zhanxuewei
发布于 2025-03-09 / 8 阅读
0
0

equals()和hashCode()有什么关系?为什么要重写它们?

一、核心概念:

1.equa1s()定义:

  • equals()是Object类中的方法,用于判断两个对象是否相等。

  • 默认实现是比较对象的引用地址(==),即它们是否是同一个对象。

  • 我们需要重写equals()方法,让其比较对象内容而非地址。

2.hashCode()定义:

  • hashCode()方法返回对象的哈希值,是一个整数,用于快速查找。

  • Java的集合框架(如HashMap、Set)通过hashCode()进行哈希分桶操作。

  • 默认实现基于对象的内存地址计算哈希值。

3.两者的关系:

  • 如果两个对象通过equals()方法判断相等,那么它们的hashCode()必须相等(保证逻辑一致)。

  • 如果两个对象的hashCode()不同,那么它们的equals()必定返回false。

  • 同一个对象在多次调用hashCode()时,应该返回相同的结果(如果对象状态未改变)。

二、为什么要重写它们?

1.为了支持集合的正常工作:

  • 当将对象存储到基于哈希的集合(如HashMap或HashSet)中,会先调用hashCode()方法定位到 哈希桶,再通过equals()确定对象是否相同。

  • 如果hashCode()和equals()不一致,则集合可能无法正确处理对象。

例如: 存在哈希冲突时,equals()用于判断是否是同一个对象。

如果只重写equals()而没有重写hashCode(),会导致逻辑错误。

2.对比内容而非引用:

开发中更常见的是基于内容的比较,例如判断两个用户是否是同一个人,不应仅仅依赖对象地址。

3.防止错误行为:

如果hashCode()的逻辑错误或未正确匹配equals(),会导致错误结果或性能下降(比如哈希碰撞过 多,导致链表长度增大)。

三、深入思考

1.违反约定的结果:

  • 如果两个对象的equals()返回true,但hashCode()不相等,哈希集合将无法正确工作,例如可能会插入重复元素。

  • 举例:HashSet中会出现"看以相等但存储多个"的情况。

2.HashMap的存储与查找过程:

  • 存储时会调用键的hashCode()计算哈希值,定位到哪个"哈希桶"。

  • 查找时会根据同样的hashCode()定位,再通过equals()确保是目标键。

四、代码演示

  • 未重写equal和hashCode:

import java.util.HashMap;

class Person {

    private String name;

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

import java.util.HashMap;

public class Demo {
    public static void main(String[] args) {
        HashMap<Person, String> map = new HashMap<>();
        Person p1 = new Person("John");
        Person p2 = new Person("John");
        map.put(p1, "Person1");
        System.out.println(map.get(p2));//null,查找时定位失败
    }
}

原因:由于p1和p2是不同的内存对象,hashCode()不同,导致它们被分配到不同的哈希桶。

  • 正确重写equals和hashCode:

import java.util.Objects;

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 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);
    }
}
import java.util.HashMap;

public class Demo {
    public static void main(String[] args) {
        HashMap<Person, String> map = new HashMap<>();
        Person p1 = new Person("John", 25);
        Person p2 = new Person("John", 25);
        map.put(p1, "Person1");
        System.out.println(map.get(p2));//输出:Person1
    }
}


评论