“深度相等”测试和hashCode()

时间:2011-09-13 20:35:52

标签: java object

假设某个班级MyClass有3个变量,abc。该类还重写了hashCode(),它使用Joshua Bloch的方法计算返回值。

假设上述情况,假设MyClass()new MyClass()如果其哈希码匹配则完全相等是否正确?

出于示例的目的,假设两个对象都使用相同的参数进行初始化

3 个答案:

答案 0 :(得分:5)

当然不是。

hashCode需要为等效对象生成相同的值,但不同的对象可能会产生相同的值。因此,以下是正确的(但效率低下的)hashCode实现:

public int hashCode()
{
    return 42;
}

即使你知道使用了特定的散列方法,假设hashCode是完美的也是一个坏主意:稍后,一些重构/子类可能会用其他东西替换hashCode实现。如果您需要这个,请创建一个始终返回完美哈希码的perfectHashCode方法,并将其用于实现hashCode

回答你的初始问题:不,即使Bloch的方法afaics也不会产生完美的hashCode,因为(因为包裹在MAXINT上)2个不同的路径最终可能会碰撞到相同的哈希码。

这很容易想象:假设您的对象包含2个整数。哈希码只有1个整数。因此,对于2个整数的每个组合,它永远不会产生不同的值。

答案 1 :(得分:0)

如果哈希码匹配,则永远不能假设两个对象相等。哈希码相等只意味着对象可能相等,并且必须调用equals来确定。哈希码不同意味着对象肯定相等(提供hashCode()正确一致equals)。

答案 2 :(得分:0)

其他答案是正确的,但这是另一种查看方式:hashCode会返回int。如果您的对象具有String作为其唯一成员且该字符串包含超过4个字节的字符,那么您在String中已经拥有的信息比使用{表示的更多信息{1}}。一旦你意识到这一点,很明显int返回的值无法完全表示对象。

由于hashCode返回的值不能完全表示对象,因此它显然不能用于确定对象在语义上是否相等。

如果两个对象的hashCode相等,你可以做的一件事:你可以假设它们是相同对象的相当合理的机会。因此,例如, hashCode首先根据哈希码找到一个哈希桶,然后查看它在那里找到的每个对象(使用HashMap),找到一个语义上等同于你实际需要的对象。