覆盖等于而不是哈希码的缺点是什么,反之亦然?

what is the disadvantage of overriding equals and not hashcode and vice versa?

我知道那里有很多类似的问题,但我对阅读的答案并不满意。我试图弄清楚,但我仍然不明白。 我所知道的是,这两个在使用 set 或 map 时很重要,尤其是 HashSet、HashMap 或 Hash 对象,它们通常使用散列机制来存储元素对象。

这两种方法都是用来判断两个Object是否相等。 为了使两个对象 A 和 B 相等,首先它们需要具有相同的哈希值(必须在同一个桶中),其次我们必须在执行 A.equals(B).

时得到 true

我不明白的是,为什么有必要覆盖这两种方法。 如果我们不覆盖哈希码会怎样。是否必须覆盖 BOTH.If 这不是覆盖 equals 而不是 hashcode 的缺点,反之亦然。

是的,当您覆盖 equals 方法时,您也必须覆盖 hashcode 方法,这是正确的。背后的原因是,在散列基本元素中,如果两个对象的 equals 方法 return 为真且它们的 hashcode 方法 return 相同的整数值,则两个对象相等。在哈希基本元素(哈希映射)中,当您首先对两个对象进行相等检查时,将调用它们的哈希码方法,如果它 return 两者的值相同,则仅调用 equals 方法。如果 hashcode 没有 return 相同的值,那么它会简单地认为两个对象不相等。默认情况下,hashcode 方法 return 一些随机值,所以如果你通过覆盖 equals 方法使两个对象在某些特定条件下相等,它们仍然不会相等,因为它们的 hashcode 值不同,所以为了使它们hascode 值等于你必须覆盖它。否则您将无法将此对象作为哈希映射的键。

正确实施 hashCode 对于您的对象成为基于散列的容器中的键是必要的。其他的就没必要了。

这就是为什么它对基于散列的容器(例如 HashMap、HashSet、ConcurrentHashMap 等)很重要

在高层次上,HashMap 是一个数组,由键的 hashCode 索引,其条目是 "chains"-(键,值)对列表,其中特定链中的所有键都具有相同的哈希码。有关哈希表的复习,请参阅 Wikipedia.

考虑如果两个键 A、B 相等但具有不同的哈希码会发生什么 - 例如,a.hashCode() == 42b.hashCode() == 37。假设你写:

hashTable.put(a, "foo");
hashTable.get(b);

因为键是相等的,你希望结果是 "foo",对吧? 但是,get(b) 将查找对应于哈希 37 的链,而 (a, "foo") 对位于对应于哈希 42 的链中,因此查找将失败,您将得到 null .

这就是为什么如果您打算将对象用作基于散列的容器中的键,则相同的对象具有相同的散列码很重要。

请注意,如果您使用非基于散列的容器,例如 TreeMap,则您不必实施 hashCode,因为容器不使用它。相反,在 TreeMap 的情况下,您应该实施 compareTo - 其他类型的容器可能有自己的要求。