我有一个类,它的相等性基于2个字段,如果任何一个相等,那么这种类型的对象被认为是相等的.我如何为这样的equals()编写一个hashCode()函数,以便当equals返回true时hashCode的一般契约保持相等?
public class MyClass { int id; String name; public boolean equals(Object o) { if (!(o instanceof MyClass)) return false; MyClass other = (MyClass) o; if (other.id == this.id || other.name == this.name) return true; return false; } }
我该如何为这个类编写hashCode()函数?我想避免像这样返回一个常数的简单案例:
public int hashCode() { return 1; }
Zach Scriven.. 23
我认为不存在非平凡的哈希码.此外,您equals()
违反了API中所述的一般合同- 它不具有传递性:
(1,2)
等于 (1,3)
(4,3)
等于 (1,3)
但是,(4,3)
是不是等于给(1,2)
.
为了完整起见,我向你展示了Skeet - Niko证明=)
声明:哈希码必须是普通的常量函数.
证明:设(a,b)
和(c,d)
是两个对象具有鲜明的散列码,即h(a,b) ? h(c,d)
.考虑对象(a,d)
.通过OP的定义,(a,d)
等于(a,b)
,(a,d)
等于(c,d)
.这从如下哈希码的合同是h(a,d) = h(a,b) = h(c,d)
; 矛盾.
我认为不存在非平凡的哈希码.此外,您equals()
违反了API中所述的一般合同- 它不具有传递性:
(1,2)
等于 (1,3)
(4,3)
等于 (1,3)
但是,(4,3)
是不是等于给(1,2)
.
为了完整起见,我向你展示了Skeet - Niko证明=)
声明:哈希码必须是普通的常量函数.
证明:设(a,b)
和(c,d)
是两个对象具有鲜明的散列码,即h(a,b) ? h(c,d)
.考虑对象(a,d)
.通过OP的定义,(a,d)
等于(a,b)
,(a,d)
等于(c,d)
.这从如下哈希码的合同是h(a,d) = h(a,b) = h(c,d)
; 矛盾.
好吧,在您的场景中,忽略API要求一秒钟,没有非常量哈希函数
想象一下,有一个具有不同值的哈希函数
(a,b),(a,c),b!= c,然后哈希(a,b)!=哈希(a,c),eventhough(a,b)=(a,c).
类似地,(b,a)和(c,a)必须发出相同的hashCode.
让我们调用哈希函数h.我们发现:
h(x,y)= h(x,w)= h(v,w)forall x,y,v,w.
因此,唯一能够做你想要的哈希函数就是常量.
我很确定Zach是对的 - 没有非平凡的哈希码可以做到这一点.
伪证明:
考虑任何两个不相等的值,X =(id1,name1)和Y =(id2,name2).
现在考虑Z =(id2,name1).这等于X和Y,因此必须具有与X和Y 相同的哈希码.因此,X和Y必须具有相同的哈希码 - 这意味着所有值必须具有相同的哈希码.
你有一个奇怪的情况 - 你正在打破平等的传递性质.X.equals(Z)和Z.equals(Y)应该表示X.equals(Y) - 但事实并非如此.你对平等的定义不适合平等的正常合同.