写两个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 的实现
相关推荐
香蕉大香蕉(06敬畏市场)6 分钟前
MySQL 单点详解(08)
java·数据库·mysql·面试·八股
thefool11226610 分钟前
HTTPS协议
java
acd1200918 分钟前
Nginx 反向代理的缓冲区坑:后端响应大时接口偶发 502
java·运维·nginx
装不满的克莱因瓶20 分钟前
支付订单成功异步MQ权益发放设计和开发
java·架构·系统架构·rabbitmq·硬件架构
凉茶钱30 分钟前
红黑树:用“颜色”换“平衡”,set 与 map 的底层发动机
开发语言·c++·红黑树
高冷小鱼殿下39 分钟前
内部类Lambda与枚举
java·开发语言
shelly聊外贸1 小时前
WhatsApp 聊天记录如何导出为 CSV?使用 Python 进行数据分析
开发语言·python·数据分析
怕浪猫1 小时前
Super-agent 在各大模型厂商的应用情况
算法·面试·github
小蒜学长1 小时前
编程语言在线学习平台的设计与实现(代码+数据库+LW)
java·spring boot·后端·编程语言在线学习平台·在线编码
Flynn Liang1 小时前
Spring AI 多模态实战(下):文生图 + TTS 语音合成(含 2.0 流式音频分片)
人工智能·spring·文生图·音视频·语音合成·tts·springai