Java hashCode 和 equals

揭秘 equals 和 hashCode
1. equals 的作用
在 Object 类的源码中,equals 方法如下定义:
|
|
简而言之,equals 方法的作用是判断两个对象是否相等。
对于没有被覆写的 Java 类,通过 equals() 进行两个对象的比较等价于 ==。对于 equals() 和 == 的区别,在 Java String及其相关类 中的字符串比较部分已举例说明。
2. 何时需要覆写 hashCode() 和 equals()?
上文提到,没有被覆写的 equals() 相当于 ==,所以要实现比较两个对象的内容是否相等,就需要覆写 equals()。
|
|
以上例子的 isEquals 方法返回 false,因为 p1 和 p2 内容虽然相同但不是相同的对象。
通过 IDE 的 生成 equals() 和 hashCode() 功能可以直接生成相应代码,后期可以根据相关业务需求进行修改。通过重写 equals() 同类型同内容不同引用的情况也能正确的返回 true。
|
|
3. 为什么覆写 equals() 时必须覆写 hashCode()?
hashCode 方法将返回 int 类型的哈希值,该值确定对象在哈希表中的索引位置。由于不可避免的会存在哈希值冲突情况(两个不同的键值对,哈希值相等),当 hashCode 相同时,还需要调用 equals() 进行比较;若 hashCode 不同,将直接判定为对象不同,而跳过执行 equals(),加快了处理效率。
假设上文例子 Person 类只覆写了 equals() 没有覆写 hashCode(),现有两个 Person 对象 p1 和 p2:
|
|
将这两个对象放到 Set 集合,输出结果是 2。根据 Set 存储的是不重复的对象,结果应该为1。但是因为没有覆写 hashCode(),即使 equals() 相等,hashCode() 得到的是一个与对象地址相关的唯一数值,hashCode() 不同,所以两个本应相等的对象被判定为不相等。如果想存储不重复的元素,那么就需要覆写 hashCode()。
hashCode 和 HashMap
equals并非万能(BigDecimal)
总结
- 如果两个对象的
equals()结果是相等的,则两个对象的hashCode()返回结果也必须是相同的;如果两个对象有相同的 hashCode 值,它们不一定是相等的(哈希冲突)。 - 任何时候覆写
equals(),都必须同时覆写hashCode(),否则两个对象无论如何都不会相等。