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 ? 那么这两个来源之间就不会有冲突。

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

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

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

这是对立的 。

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

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

这两个陈述是等价的。

简单地说:

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

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

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

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

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

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

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

如果未正确处理hashCode / equals合约,则结果如此。

  hashCode()|  equals()|  被视为|  描述 
 没有| 没有| 重复| 存放在不同的桶中。
                                              | 被视为不同的对象。

是的| 没有| 重复| 存放在同一个桶中。
                                              | 被视为不同的对象。 
                                              | 因为,默认(对象)等于方法将仅检查对象的引用。     

没有| 是的| 重复| 存放在不同的桶中。作为不同的对象处理

是(hashlogic)| 是的| 独特| 存储在同一个桶中。作为同一个对象。高效。

是(常数)| 是的| 独特| 存储在同一个桶中。作为同一个对象处理。
                                              | 效率低下,因为它将迭代桶元素进行相等性检查。

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

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