向集合中添加对象时,是否需要同时覆盖equals和hashcode方法?

3

最近有一位面试官问我,我有一个类,在其中覆盖了其equals()方法,但没有覆盖我的hashCode()方法。

现在是否需要也覆盖我的hashCode()方法呢?

如果我不覆盖我的哈希码方法会发生什么,将会维护其不允许重复的唯一属性吗?

这个问题涉及到Set的内部实现,我的困惑在于,如果两个对象返回不同的hashCode(),那么根据我的理解它们的equals()不会被检查,然后如果这两个对象相等,则会违反Set的唯一属性。

这是真的吗?

4个回答

2
具体取决于具体的Set实现,正如Collection文档(Collection是Set的超类)所提到的那样。对象的hashCode()规范保证了具有不相等哈希码的两个对象不能相等。更一般地说,各种集合框架接口的实现在实现者认为适当的任何地方都可以利用底层对象方法的指定行为。例如,HashSet(顾名思义)将使用哈希值,而其他Set的实现可能不会,并且仅使用equals()。最后,Object.equals文档中给出了一些好的建议:请注意,通常需要重写hashCode方法,以便维护hashCode方法的一般契约,该契约规定相等的对象必须具有相等的哈希码。

1

您应该始终覆盖这两个方法。它们是合同的一部分。

查看Java文档并确保满足其中的详细信息。 Eclipse也可以为您生成这些方法。


1
最简单的理解方式是将哈希码看作桶。当您将对象存储在集合中时,它们会根据计算出的哈希码进入这些桶中。
当您重写equals方法时,即一个对象等于另一个对象时,它们应该落入同一个桶中。
但是,如果您没有重写哈希码方法来确保这一点,情况就不会如此。
因此,JVM会尝试在错误的桶中搜索对象。找不到它,结果就会产生重复项。(顺便说一下,我的面试也快开始了,真的很害怕!)

0

两者都是推荐的。

例如,如果您有一个超类Person,具有属性idnamesurname,并且您基于namesurname定义了equalshashCode,以及一个具体的子类Contact Person,具有额外的属性,如email,则重要的是为您的类Contact Person定义新的equalshashCode。如果您的具体类Contact Person实现了一个将email属性作为唯一字段的实体,则仅基于email重新定义equalshashCode就足够了。不过,基于namesurnameemail定义一个新的equalshashCode更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接