当前位置:  开发笔记 > 编程语言 > 正文

当equals()基于多个独立字段时,hashCode()方法

如何解决《当equals()基于多个独立字段时,hashCode()方法》经验,为你挑选了3个好方法。

我有一个类,它的相等性基于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); 矛盾.



1> Zach Scriven..:

我认为不存在非平凡的哈希码.此外,您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); 矛盾.



2> nes1983..:

好吧,在您的场景中,忽略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.

因此,唯一能够做你想要的哈希函数就是常量.


+1作为证明,我无耻地将其用作我的基础。

3> Jon Skeet..:

我很确定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) - 但事实并非如此.你对平等的定义不适合平等的正常合同.


嗯,这就像zach所说的那样,只是更加臃肿.
推荐阅读
kikokikolove
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有