『Java 语法基础』对 equals() 和 hashCode() 的理解

为什么在重写 equals 方法的时候需要重写 hashCode 方法

因为有强制的规范指定需要同时重写 hashcode 与 equals 方法,许多容器类,如 HashMap、HashSet 都依赖于 hashcode 与 equals 的规定。

在Java中,equals()hashCode() 方法是 Object 类的两个非常重要的方法,它们用于比较对象的相等性以及计算对象的哈希码。

equals() 方法用于判断两个对象是否逻辑上相等,也就是两个对象的内容是否相同。它通常需要根据实际情况在子类中重写,以提供正确的相等性逻辑。默认情况下(如 Object 类中的实现),equals() 方法比较对象的内存地址,也就是说,只有同一个对象才被认为是相等的。

hashCode() 方法则用于计算对象的哈希码,它被用于散列数据结构,如 HashSetHashMap 等。在散列数据结构中,对象的哈希码通常被用来决定对象应该存放的位置。

根据 Java 规范,有关 equals()hashCode() 的重要契约包括:

  1. 如果两个对象相等,那么它们的 hashCode() 方法必须返回相同的整数。
  2. 如果两个对象的 hashCode() 方法返回相同的整数,这并不要求它们一定相等,但散列表的效率可能受到影响。

之所以在重写 equals() 方法时必须同时重写 hashCode() 方法,是为了维持这两个方法之间的一致性。如果两个对象是相等的,但它们的哈希码不相同,这将违反 hashCode() 方法的契约,可能导致无法正确地存取散列数据结构中的对象。例如,在使用 HashMap 时,如果两个键对象相等,它们必须具有相同的哈希码,否则可能会导致其中一个对象无法被正确地找到。

有没有可能两个不相等的对象有相同的 hashcode?

有可能,即使两个对象不相同,它们也可能具有相同的 hashCode 值,这称为哈希冲突。哈希冲突是散列算法的一个固有属性,因为散列码是将对象信息映射到一个有限的整数域上。由于这个整数域范围的限制,相对于可能的对象状态来说是不足够的,从而导致不同对象间的哈希值可能相同。

Java语言规范中关于 hashCode 的合同确实指出,如果两个对象相同,则它们的哈希码一定相同,但并未规定不同的对象必须产生不同的哈希码。因此,在基于哈希的数据结构中,如 HashMap,便可能出现哈希碰撞。在这种情况下,HashMap 会使用 链表红黑树 来管理相同哈希码的不同键,确保了即便发生了哈希碰撞,也能通过 equals() 方法准确地区分和处理这些键。

因此,为了确保诸如 HashMapHashSet 这样的基于哈希的集合能够正确且高效地运作,合理地实现 hashCodeequals 方法以及妥善处理哈希冲突是至关重要的。

两个相同的对象会有不同的 hash code 吗?

不能,根据 hash code 的规定,这是不可能的。

在 Java 中,当你重写一个类的 equals() 方法时,根据 Java 的规范,你也必须重写 hashCode() 方法,以保证同一个类的两个相等的对象(即 equals() 方法返回 true)返回相同的 hash code 值。这是因为 Java 中的集合类,如 HashMapHashSet,依赖于 hashCode()equals() 方法来确定对象的唯一性。

如果两个对象根据 equals(Object) 方法是相等的,那么它们的 hashCode()方 法也必须返回相同的整数值。如果没有重写 hashCode(),那么默认的 Object 类的实现将产生基于对象内存地址的 hash code,这可能会违反这一规定,并且在使用哈希表的过程中导致性能下降。所以重写 equals() 时一定要同步重写 hashCode(),以确保行为的一致性。

posted @ 2024-03-18 00:57  BNTang  阅读(48)  评论(0)    收藏  举报