最近一位采访者问我,我有一个班级,我已经覆盖了equals()
方法,但没有覆盖我的hashCode()
方法。
现在是否有必要覆盖我的hashCode()
方法。
如果我不覆盖我的hashcode方法会发生什么,将设置保持其不允许重复的唯一属性。?
问题是关于Set
的内部实现,这里我的困惑是两个对象返回不同的hashCode()
,据我说他们的equals()
将不会被检查,然后是唯一的如果两个对象相等,则会违反Set
的属性。
这是真的吗?
答案 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,
,name
,surname
,并且您根据equals
定义hashCode
和name
和surname
以及具有Contact Person
等额外属性的具体子类email
,为您的班级定义新的equals
和hashCode
非常重要{ {1}}。如果您的具体类Contact Person
实现了将Contact Person
属性作为唯一字段的实体,则仅基于email
重新定义equals
和hashCode
就足够了。但是,根据email
,equals
和hashCode
定义新的name
和surname
会更好。