在审核大型代码库时,我经常会遇到这样的情况:
@Override
public int hashCode()
{
return someFieldValue.hashCode();
}
程序员不是为类生成自己唯一的哈希代码,而是从字段值继承哈希代码。我的直觉(也可能是消化问题)告诉我这是错的,但我不能把手指放在上面。如果有这种实施,会出现什么问题?
答案 0 :(得分:16)
如果您想基于单个属性对对象进行哈希,那么这很好。
例如,在Person
类中,您可能拥有唯一标识Person
的ID属性,因此hashCode()
的{{1}}可能只是其中的哈希值ID。
此外,Person
与hashCode()
的实施有关。如果两个对象相等,则它们必须具有相同的equals
(相反的情况不一定是真的 - 两个不相等的对象可能仍然具有相同的hashCode)。因此,如果相等由单个属性(例如唯一ID)确定,则hashCode
方法也必须仅使用该单个属性。
这可以在hashCode的JavaDoc中看到:
hashCode的一般合约是:
- 每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是不修改对象的equals比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,此整数不需要保持一致。
- 如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须生成相同的整数结果。
- 如果两个对象根据equals(java.lang.Object)方法不相等,则不需要在两个对象中的每一个上调用hashCode方法必须生成不同的整数结果。但是,程序员应该知道为不等对象生成不同的整数结果可能会提高哈希表的性能。
答案 1 :(得分:10)
从技术上讲,你可以从hashCode
返回任何一致的数字,即使是一个常数值。唯一的requirement the contract places upon you是相等的对象必须返回相同的哈希码:
如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用
hashCode
方法必须产生相同的整数结果。
理论上,如果所有对象返回(例如)为hashCode
的零,则合同正式得到满足。但是,这会使hashCode
完全失效。
真正的问题是你是否应该这样做。答案取决于您要返回的哈希码的字段的唯一性。为对象的hashCode
返回对象的唯一标识符的hashCode
并不罕见。另一方面,如果相当大比例的对象具有someFieldValue
的理智值,那么最好使用不同的策略来制作对象的哈希码。
答案 2 :(得分:3)
hashCode()
必须与equals()
一起使用。
如果唯一定义相等性的属性是,例如,ID,那么当ID相等时,您必须注意哈希码是相等的。
完成此操作的最简单方法是获取您的ID的hashCode()
。
答案 3 :(得分:2)
如果你真的想通过这个属性唯一地识别你的对象,这很好。这是一个article,它解释了真正的对象身份。
正如Object
文档中所述,您的equals()
和hashCode()
需要包含相同的属性,请务必验证。
所以这意味着你应该问自己一个问题:如果只有这个单一的属性相等,我真的希望对象是平等的吗?
最后在使用自定义equals()
和hashcode()
实现子类化对象时要特别小心,如果要向对象的标识添加属性,则会破坏{{1}的要求(看看为什么这个失败了,因为a.equals(b) == b.equals(a)
是超类,而a
是子类。
答案 4 :(得分:-2)
是的,你可以在技术上做到这一点,你需要一个非原始的somefieldValue。