关于下面提到的3份合同:
1)每当在执行应用程序期间多次在同一对象上调用
hashCode()
时,hashCode
方法必须始终返回相同的整数,前提是没有在等于比较的信息中使用对象被修改。从应用程序的一次执行到同一应用程序的另一次执行,此整数不需要保持一致。
从这个陈述中,我理解,在单次执行应用程序时,如果在同一个对象上使用hashCode()
一次或多次,它应返回相同的值。
2)如果两个对象根据
equals(Object)
方法相等,则在两个对象中的每一个上调用hashCode()
方法必须产生相同的整数结果。
从这个陈述中,我理解,要在子类中执行相等操作(在宽范围内),至少有四种不同的相等程度。
(a)引用相等(==),比较两个引用类型对象的内部地址。
(b)浅层结构等式:如果所有字段都是==,则两个对象为“等于”。
{例如,两个SingleLinkedList
的“大小”字段相等,其“head”字段指向相同的SListNode
。}
(c)深度结构平等:如果所有字段都是“等于”,则两个对象为“等于”。
{例如,两个SingleLinkedList
表示相同的“项目”序列(尽管SListNodes
可能不同)。}
(d)逻辑平等。 {两个例子: (a)如果两个“Set”对象包含相同的元素,则它们是“equals”,即使基础列表以不同的顺序存储元素也是如此。 (b)分数1/3和2/6是“等于”,即使它们的分子和分母都不同。}
基于以上四类相等,第二个合同只能保持良好:如果(Say)equals()
方法基于两个对象之间的logical_equality返回真值,那么hashCode()
方法必须在为每个新对象生成整数之前,还考虑计算中的logical_equality,而不是考虑新对象的内部地址。
但我在理解第三份合同时遇到了问题。
3)如果两个对象根据
equals(Object)
方法不相等,则不需要这样做,那么在两个对象中的每一个上调用hashCode()
方法必须产生不同的整数结果。但是,程序员应该知道为不等对象生成不同的整数结果可能会提高哈希表的性能。
在第二份合同中,正如我们所说hashCode()
方法应该相应地[例如:考虑生成整数之前的logical_equality]实现,我觉得,不是真的来说,如果根据equals(Object)
两个对象不相等,那么hashCode()
方法可能产生与第三个合同中提到的相同的整数结果?根据第二个合同中的参数,hashCode()
必须生成不同的整数结果。只需在return 42
中撰写hashCode()
即可打破第二份合约!
请帮助我理解这一点!
答案 0 :(得分:5)
hashCode()
不可能总是为不等对象返回不同的值。例如,有2 ^ 64个不同的Long
值,但只有2 ^ 32个可能的int
值。因此,hashCode()
的{{1}}方法必须重复一些。在这种情况下,您必须努力确保您的Long
方法尽可能均匀地分配值,并且不太可能为您最有可能在实践中使用的实例生成重复。
第二个条件只是说两个hashCode()
实例必须返回相同的equal()
值,因此该程序必须打印为true:
hashCode()
但是这个程序也打印为true:
Long a = Long.MIN_VALUE;
Long b = Long.MIN_VALUE;
System.out.println(a.hashCode() == b.hashCode()); // a.equals(b), so must print true.
答案 1 :(得分:1)
hashCode()
不会产生明显的结果。 return 0;
是hashCode()
完全合法的实现 - 它确保两个equal
对象具有相同的哈希码。但是,在使用HashMap
和HashSet
时,它会确保令人沮丧的效果。
hashCode()
返回值最好是不同的(即,不相等的对象应该有不同的哈希码),但不是必需的。
答案 2 :(得分:1)
第二份合同规定了equals()
返回true
时会发生什么。当equals()
返回false
时,它没有说明这种情况。
第三份合同只是对这一事实的提醒。它提醒您,当equals()
为false
两个对象时,它们的哈希码之间没有连接。它们可能相同或不同,因为实现恰好是它们。
答案 3 :(得分:0)
第三点意味着您可以拥有许多具有相同哈希码的不等对象。 。例如,2个字符串对象可以具有相同的哈希码。第二点指出两个相等的对象必须具有相同的哈希码。 。 return 5是一个有效的哈希实现,因为它为2个相等的对象返回相同的值。