Java中的equals()和hashCode()契约

时间:2011-03-04 21:56:01

标签: java equals hashcode

Bert Bates和Kathy Sierra的SCJP 6学习指南在第554页(以及其他要求中)指出 x.hashCode()!= y.hashCode()要求x.equals(y)== false

但是Javadoc for Object没有明确提到这样的要求。报价:
如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须产生相同的整数结果。

我应该采用Javadoc所说的物质含义,例如 eq - > HC ?然后这两个来源之间不会发生冲突。

5 个答案:

答案 0 :(得分:13)

这两个陈述是等价的。

简单地说:

  1. 如果两个哈希码不同,则对象在equals下肯定是不同的。
  2. 如果两个哈希码相同,我们不知道。 (但在许多实际情况下,对象将是相同的)。

答案 1 :(得分:13)

正如z5h所说,这些陈述是等价的。

对于逻辑条件x和y,“x暗示y”与“!y暗示!x”相同。

“如果有东西是公共汽车,它是红色的”在逻辑上等同于“如果某些东西不是红色的,那它就不是公共汽车。”

这是contraposition

  

我应该采用Javadoc所说的物质含义,例如eq - > HC。

是的,这正是它所说的:在equals下两个对象相等意味着它们的哈希码必须相等。

答案 2 :(得分:6)

这些陈述之间没有冲突,它们是等价的。

p: x.equals(y)
q: x.hashCode() == y.hashCode()
p implies q
not q implies not p

答案 3 :(得分:2)

关于HashMap的基本事实。
 1. HashMap将为每个键生成哈希码,而不管对象类型如何  2.具体来说 - 哈希码将根据密钥和值(即条目)生成

<强>实验: 考虑用户定义的对象(例如SPObject)是散列映射的关键; SPObject中只有一个参数( name )。请参阅:http://www.programcreek.com/2011/07/java-equals-and-hashcode-contract/

如果在SPObject类中没有正确编写hashCode()和equals(),则问题如下:
放2个条目 - 新SPObject(“SP”)&amp;新的SPObject(“SP”)。这些被视为不同的对象并成功存储在Map中。

map.get(new SPObject(“SP”))将返回null map.contains(new SPObject(“SP”))将返回false。

如果hashCode / equals合约处理不当,则结果如此。

hashCode()     |    equals()    | Treated as | Description
No             |      No        | Duplicate  | Stored in different buckets.
                                             | Treated as different object.

Yes            |      No        | Duplicate  | Stored in same bucket.
                                             | Treated as different object. 
                                             | Because, the default(Object) equals method will check only the reference of objects.     

No             |      Yes       | Duplicate  | Stored in different buckets.Treated as different object

Yes(hashlogic) |      Yes       | Unique     | Stored in same bucket.Treated as same object.Efficient.

Yes(constant)  |      Yes       | Unique     | Stored in same bucket.Treated as same object.
                                             | Inefficient, because it will iterate bucket elements for equality check.

答案 4 :(得分:0)

hashCode背后的基本思想是,一个实体知道一个对象已经报告了一个hashCode值,该值不同于其他一些对象有权假定这些对象是不相等的,而不必进一步检查它们。因为整数支持与等价相关的各种公理,所以实体可以知道两个哈希码的不同而不直接比较它们。例如,知道其中一个报告了偶数而另一个报了奇数就足以表明它们无法匹配。这样的假设通常允许实体快速识别大部分集合,这些集合不可能包含被查找的对象,因此不会费心检查这些区域。

关于hashCode和equals的两个引用的“要求”都包括一个未说明的前提:在X.equals(Y)报告为真的情况下,人们不希望实体错误地认为它是假的。一般来说,代码根据错误的假设行事是非常糟糕的,因此人们不希望实体对对象的相等性做出错误假设的前提是合理的。 “学习指南”引用了一个事实,即如果两个对象具有不相等的哈希码,则它们将被假定为不相等;使这种假设符合现实要求他们 不平等。 JavaDoc实质上暗示如果两个对象相等,并且想要避免让实体假设它们不会并且没有注意到它们是,则必须确保一个对象返回的hashCode值另一方也会回来。