侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

深入理解Java中的equals()和hashCode()方法

2025-12-5 / 0 评论 / 4 阅读

题目

深入理解Java中的equals()和hashCode()方法

信息

  • 类型:问答
  • 难度:⭐⭐

考点

对象相等性,哈希原理,集合框架,方法重写规范

快速回答

核心要点:

  • 重写equals()时必须同时重写hashCode()
  • 两个对象equals()相等时,其hashCode()必须相等
  • 哈希冲突时不同对象可能有相同哈希值
  • 违反规则会导致HashMapHashSet等集合行为异常
## 解析

1. 原理说明

Java中对象相等性判断基于两个层次:

  • equals():逻辑相等性(默认使用==比较内存地址)
  • hashCode():为对象生成哈希码,用于哈希表快速定位

在哈希集合(如HashMap)中,先通过hashCode()定位桶位置,再用equals()精确匹配。若违反以下契约会导致集合行为异常:

强制契约:

  1. 两个对象equals()相等 → 其hashCode()必须相等
  2. 两个对象equals()不相等 → hashCode()可以相等(哈希冲突)

2. 代码示例

public class Person {
    private String name;
    private int 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() {
        // 使用JDK提供的Objects工具类
        return Objects.hash(name, age);
    }
}

3. 最佳实践

  • 字段选择:使用equals()中比较的相同字段计算哈希码
  • 工具类:优先使用Objects.hash(field1, field2...)简化实现
  • 不可变字段:避免使用可变字段计算哈希码(否则集合中元素会"消失")
  • 性能优化:对于复杂对象,可缓存哈希码(需确保对象不可变)

4. 常见错误

错误类型后果示例
只重写equals()HashMap.get()可能返回null两个equals相等的对象在HashMap中被存到不同桶
使用可变字段集合元素"丢失"对象存入HashSet后修改参与哈希计算的字段
忽略null安全NullPointerException未处理字段为null的情况

5. 扩展知识

  • 哈希冲突处理:Java 8+的HashMap使用链表+红黑树,当链表长度>8时转树
  • Lombok注解@EqualsAndHashCode可自动生成合规实现
  • IdentityHashMap:特殊Map使用==代替equals(),不依赖hashCode
  • 性能影响:差的hashCode实现(如所有实例返回1)会使HashMap退化为链表