重写 HashCode,什么时候这样做不会有问题?

Overriding HashCode, when would not doing so be problematic?

重写对象的等号运算符来比较字段时,也说你应该重写hashCode()。

是否会出现两个对象具有所有相同字段但不同 hashCodes() 的情况?为什么需要同时更新两者?

a.equals(b) 意味着 map.put(a, c); map.get(b) 应该产生 c,其中 mapMapab是键,c 是一些值。特别是,HashMap 可以非常快速地执行这些操作,但依赖于 a.hashCode()b.hashCode() 才能正确执行。如果 a.hashCode() != b.hashCode() 那么它们将不会被识别为相等的键,并且使用 HashMap 的程序将以非常令人沮丧和混乱的方式出现错误行为。您应该始终假设这是一种可能性,即使您目前不打算这样做。 不要缺一不可。这也不难做到:您的 IDE 可能会为您生成它(和 equals)。其他数据结构如HashSet也使用它。

重写两者的主要问题是许多容器假定这两种方法使用相同的策略。

典型情况是 HashMap,如果您重写 equals()/hashCode() 中的一个而不是两者(或不一致地重写它们),它们可能无法工作,因为它们使用 hashCode() 来查找您的存储桶键应该是,然后使用 equals() 在该桶内搜索。所以它可能最终会在错误的桶中搜索给定的键!。顺便说一句,这就是为什么有时在 get() 时找不到键,但可以通过遍历每个元素找到它的原因:迭代不使用 hadhCode()。

这与为什么你应该 永远不会 有一个 hashCode() 在对象位于 HashSet/HashMap 中时更改其值的原因类似:当你搜索您的对象,hashCode() 可能已更改并将您发送到不正确的存储桶。