equals 方法的一般合同中有一点,它说如果你定义了equals()
方法,那么你也应该定义hashCode()
方法。如果o1.equals(o2)
那么这是必须的o1.hashCode() == o2.hashCode()
。
所以我的问题是,如果我违反了这份合同怎么办?o1.equals(o2)
但是哪里会带来失败的情况o1.hashCode != o2.hashCode()
呢?
equals 方法的一般合同中有一点,它说如果你定义了equals()
方法,那么你也应该定义hashCode()
方法。如果o1.equals(o2)
那么这是必须的o1.hashCode() == o2.hashCode()
。
所以我的问题是,如果我违反了这份合同怎么办?o1.equals(o2)
但是哪里会带来失败的情况o1.hashCode != o2.hashCode()
呢?
它将导致基于哈希的数据结构中出现意外行为,例如:HashMap
,阅读 HashTable 的工作原理
HashMap/HashTable/HashSet/etc 将根据其将您的对象放入多个存储桶之一hashCode
,然后检查该存储桶中是否有任何其他对象equal
。
因为这些类假定 equals/hashCode 契约,它们不会检查其他存储桶中的对象是否相等。毕竟,另一个桶中的任何对象都必须具有不同的 hashCode,因此(根据合同)不能等于问题中的对象。如果两个对象equal
具有不同的哈希码,它们可能最终位于不同的桶中,在这种情况下,HashMap/Table/Set/etc 将没有机会比较它们。
因此,您最终可能会得到一个包含两个相等对象的 Set —— 这是不应该做的;或包含同一个键的两个值的 Map(因为桶是键);或您无法查找键的 Map (因为查找同时检查哈希码和相等性);或任何数量的类似错误。
如果您违反合同,您的对象将无法与基于散列的容器(以及任何其他使用hashCode()
并依赖其合同的容器)一起使用。
基本直觉如下:看两个对象是否相同,容器可以同时调用hashCode()
两者,比较结果。如果哈希码不同,则通过假设两个对象不相等来允许容器短路。
举一个具体的例子, if o1.equals(o2)
but o1.hashCode() != o2.hashCode()
,您可能能够将两个对象都插入到 aHashMap
中(这意味着存储唯一的对象)。