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

Java中的equals()和hashCode()契约,java,equals,hashcode,Java,Equals,Hashcode,伯特·贝茨(Bert Bates)和凯西·塞拉(Kathy Sierra)的SCJP 6研究指南在第554页(以及其他要求)中指出,x.hashCode()!=y、 hashCode()要求x.equals(y)=false 但是JavadocforObject并没有明确提到这样的需求。引用: 如果根据equals(Object)方法两个对象相等,那么对两个对象中的每一个调用hashCode方法必须产生相同的整数结果 我是否应该将Javadoc所说的内容视为实质性的暗示,例如eq->hc?那么这

伯特·贝茨(Bert Bates)和凯西·塞拉(Kathy Sierra)的SCJP 6研究指南在第554页(以及其他要求)中指出,x.hashCode()!=y、 hashCode()要求x.equals(y)=false

但是JavadocforObject并没有明确提到这样的需求。引用:
如果根据equals(Object)方法两个对象相等,那么对两个对象中的每一个调用hashCode方法必须产生相同的整数结果


我是否应该将Javadoc所说的内容视为实质性的暗示,例如eq->hc?那么这两种来源之间就不会有冲突。

这两种说法是等价的

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

  • 如果两个hashcode不同,那么对象在equals下肯定不同
  • 如果两个哈希码相同,我们就不知道了。(但在许多实际情况下,对象是相等的)
    正如z5h所说,这些语句是等价的

    p: x.equals(y)
    q: x.hashCode() == y.hashCode()
    p implies q
    not q implies not p
    
    对于逻辑条件x和y,“x暗示y”与“!y暗示!x”相同


    “如果某物是总线,它是红色的”在逻辑上等同于“如果某物不是红色,它不是总线。”

    这是

    我是否应该将Javadoc所说的内容视为实质性的暗示,比如eq->hc


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

    这些语句之间没有冲突,它们是等价的

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

    关于HashMap的基本事实。
    1.HashMap将为每个键生成hashcode,而不考虑对象类型。
    2.具体来说,hashcode将基于键和值(即条目)生成

    实验: 考虑一个用户定义的对象(例如SPObjt)是一个HASMAP的关键;SPObject中只有一个参数(名称)。参考:

    如果在SPObject类中没有正确编写hashCode()和equals(),则问题如下。
    放置两个条目-新SPObject(“SP”)和新SPObject(“SP”)。它们被视为不同的对象,并成功地存储在映射中

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

    如果hashCode/equals契约处理不当,则会出现这种情况

    hashCode() | equals() | Treated as | Description hashCode()| equals()|视为|描述 不|不|重复|存储在不同的桶中。 |被视为不同的对象。 是|否|重复|存储在同一桶中。 |被视为不同的对象。 |因为,默认的(Object)equals方法将只检查对象的引用。 否|是|重复|存储在不同的桶中。视为不同的对象 是(hashlogic)|是|唯一|存储在同一个存储桶中。作为同一对象处理。高效。 是(常量)|是|唯一|存储在同一个桶中。视为同一对象。 |效率低下,因为它将迭代bucket元素进行相等性检查。
    hashCode
    背后的基本思想是,一个实体知道一个对象报告的hashCode值不同于其他对象有权假设对象不相等,而无需进一步检查它们。由于整数支持与等价性相关的各种公理,实体可能知道两个哈希代码不同,而无需直接比较它们。例如,如果知道其中一个报告了偶数,而另一个报告了奇数,就足以表明它们无法匹配。这样的假设通常允许实体快速识别集合中不可能包含正在查找的对象的大部分,从而不必检查这些区域


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

    感谢您的澄清!“如果某物是一辆公共汽车,它是红色的”你真是英国人:-)乔恩,你能给我举个例子,说明HashCode可以相同,但对象不相等吗?@UnKnown:Sure-
    Long.valueOf(1)
    Long.valueOf(1L@UnKnown:因为它对于散列码来说不是必需的。不管怎样,
    int
    中的散列冲突是很少见的。你只需要知道散列不是唯一的,也不是唯一的。解释得很好!!