要在set中添加对象,是否有必要重写equals和hashcode。

时间:2016-06-11 08:09:42

标签: java data-structures equals hashcode hashset

最近一位采访者问我,我有一个班级,我已经覆盖了equals()方法,但没有覆盖我的hashCode()方法。

现在是否有必要覆盖我的hashCode()方法。

如果我不覆盖我的hashcode方法会发生什么,将设置保持其不允许重复的唯一属性。?

问题是关于Set的内部实现,这里我的困惑是两个对象返回不同的hashCode(),据我说他们的equals()将不会被检查,然后是唯一的如果两个对象相等,则会违反Set的属性。

这是真的吗?

4 个答案:

答案 0 :(得分:1)

您应该始终覆盖两者。它们是合同的一部分。

查看java文档并确保您在那里完成详细信息。 Eclipse也可以为您生成这些方法。

答案 1 :(得分:1)

理解这一点的最简单方法是将哈希码视为存储桶。当您将对象存储在集合中时,它们会根据计算出的哈希码转到这些存储桶。

当你重写equals时,这是一个对象等于另一个,所以它们应该落在同一个桶中。

然而事实并非如此,因为您没有覆盖哈希码方法以确保这一点。

所以jvm会尝试在错误的桶中搜索对象。找不到它,因此你会有重复。 (顺便说一下,我的采访很快就开始了,非常害怕!)

答案 2 :(得分:1)

这实际上取决于具体的Set - 实现,如Collection doc所述(集合是Set的超类)

  

(Object.hashCode()规范保证两个对象具有   不等的哈希码不能相等。)更一般地说,实现   可以免费使用各种Collections Framework接口   底层Object方法的指定行为的优点   实施者认为合适的地方。

因此,例如HashSet(顾名思义)将使用哈希值,Set的其他实现可能不会 - 并且只使用equals()

最后来自Object.equals doc的一些好建议:

  

请注意,通常需要覆盖hashCode方法   每当重写此方法时,以便维护一般   hashCode方法的契约,它声明了相等的对象必须   有相同的哈希码。

答案 3 :(得分:0)

总是建议两者。

E.g。如果您的超类Person包含属性id,namesurname,并且您根据equals定义hashCodenamesurname以及具有Contact Person等额外属性的具体子类email,为您的班级定义新的equalshashCode非常重要{ {1}}。如果您的具体类Contact Person实现了将Contact Person属性作为唯一字段的实体,则仅基于email重新定义equalshashCode就足够了。但是,根据emailequalshashCode定义新的namesurname会更好。