写两个hascode和equals的例子

目录

[示例1:不重写 hashCode 和 equals](#示例1:不重写 hashCode 和 equals)

[示例2:只重写 equals 方法](#示例2:只重写 equals 方法)

[示例3:正确重写 equals 和 hashCode](#示例3:正确重写 equals 和 hashCode)

示例4:在哈希集合中的行为

关键规则总结:


我将通过几个例子来帮助你理解 hashCode 和 equals 方法的作用和使用场景。

示例1:不重写 hashCode 和 equals

复制代码
public class Person {
    private String name;
    private int age;

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

    public static void main(String[] args) {
        Person p1 = new Person("Alice", 25);
        Person p2 = new Person("Alice", 25);

        System.out.println(p1.equals(p2)); // false
        System.out.println(p1.hashCode() == p2.hashCode()); // false
    }
}

解释:

  • 默认的 equals 方法比较的是对象的引用(是否为同一个对象)
  • 默认的 hashCode 返回对象的内存地址转换后的整数
  • 即使两个对象内容相同,它们也是不同的对象实例

示例2:只重写 equals 方法

复制代码
public class Person {
    private String name;
    private int age;

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

    // 重写equals方法
    @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 && name.equals(person.name);
    }

    public static void main(String[] args) {
        Person p1 = new Person("Alice", 25);
        Person p2 = new Person("Alice", 25);

        System.out.println(p1.equals(p2)); // true
        System.out.println(p1.hashCode() == p2.hashCode()); // false
    }
}

解释:

  • 重写后 equals 根据内容判断为 true
  • 但 hashCode 仍基于内存地址,导致哈希值不同
  • 问题 :这违反了 hashCode 的约定(相等的对象必须有相同的哈希值)

示例3:正确重写 equals 和 hashCode

复制代码
import java.util.Objects;

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

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

    // 重写equals方法
    @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 && name.equals(person.name);
    }

    // 重写hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    public static void main(String[] args) {
        Person p1 = new Person("Alice", 25);
        Person p2 = new Person("Alice", 25);

        System.out.println(p1.equals(p2)); // true
        System.out.println(p1.hashCode() == p2.hashCode()); // true
    }
}

解释:

  • equals 根据内容判断对象是否相等
  • hashCode 根据内容计算哈希值
  • 符合 Java 规范:相等的对象必须有相同的哈希值

示例4:在哈希集合中的行为

复制代码
import java.util.HashSet;
import java.util.Set;

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 o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && name.equals(person.name);
    }

    @Override
    public int hashCode() {
        return name.hashCode() + age;
    }

    public static void main(String[] args) {
        Set<Person> set = new HashSet<>();
        set.add(new Person("Bob", 30));
        set.add(new Person("Bob", 30));

        System.out.println(set.size()); // 1
    }
}

解释:

  • 由于正确重写了 equals 和 hashCode
  • HashSet 能够正确判断两个内容相同的对象为重复元素
  • 如果没有正确重写这两个方法,Set 会包含重复元素

关键规则总结:

  1. equals 的约定:
    • 自反性:x.equals(x) 必须为 true
    • 对称性:x.equals(y) 为 true 时,y.equals(x) 也必须为 true
    • 传递性:如果 x.equals(y) 和 y.equals(z) 为 true,则 x.equals(z) 也必须为 true
    • 一致性:多次调用 x.equals(y) 结果不变
    • 任何非 null 对象与 null 比较结果为 false
  1. hashCode 的约定:
    • 相等的对象必须具有相同的哈希值
    • 哈希值在对象的生命周期内不应改变
    • 不相等的对象可以有相同的哈希值(哈希冲突)
  1. 最佳实践:
    • 当重写 equals 方法时,必须重写 hashCode 方法
    • 使用相同的字段来计算 equals 和 hashCode
    • 可以使用 Objects.hash() 方法简化 hashCode 的实现
相关推荐
夏幻灵6 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
程序猿编码6 小时前
榨干 RTX5090 算力!Qwen3 专用单卡推理引擎,手写C++/CUDA 算子实现 MTP 推测解码
开发语言·c++·大模型推理·qwen3·多模态推理
姜鱼问生6 小时前
Nginx 缓存命中率监控:从 X-Cache-Status 到实时统计
运维·nginx·缓存
bkspiderx7 小时前
Qt 插件机制:动态扩展应用功能的核心框架
开发语言·qt·元数据·qt 插件·qpluginloader
代码什么用8 小时前
Spring基础使用
java·后端·spring
代码什么用8 小时前
Spring对IoC的实现
数据库·spring
程序员老陆8 小时前
深入理解 C++ thread_local:线程私有存储的正确打开方式
开发语言·c++·程序设计
沐晓时光8 小时前
C语言入门,深入理解指针(3)
c语言·开发语言
信奥卷王8 小时前
[GESP202609 六级] 分树规划
算法
Su米苏8 小时前
Spring AI 中MCP 与普通 @Tool的区别
java·人工智能·spring