多个字段生成Java的hashCode

8

假设我们有如下的一个类:

class MyObject {
  private String id1;
  private String id2;

  @Override
  public boolean equals(Object o) {
    if (o == this) return true;
    if (!(o instanceof MyObject)) {
        return false;
    }
    MyObject other = (MyObject) o;
    return id1.equals(other.id1) || id2.equals(other.id2);
  }
}

请注意,相等性不取决于两个字段是否匹配,任何一个字段都可以。对于这个类,什么样的hashCode实现会更合适?

我不相信有任何哈希码可以用于此。 - Andreas
@Andreas,你可以使用两者中的最小值。 - Andy Turner
4
不行。["@AndyTurner No you can't. ["A", "B"] vs ["C", "B"] are equal, but lowest hash code is not."]的意思是,["A", "B"]和["C", "B"]是相等的,但最低的哈希代码不同。请注意保持翻译后的内容与原文意思一致,同时尽可能通俗易懂。 - Andreas
4
@Andreas,但是这个平等的定义是否违反了等式的一般契约(特别是传递性)呢? - Andy Turner
1
@AndyTurner 是的,但是一个常量并不是很好的哈希码。它可以工作,但基本上将HashMap转换为LinkedList - Andreas
显示剩余2条评论
1个回答

10

这不是equals方法的有效实现。

具体来说,它违反了传递性要求。

因此,你不能"正确地"实现hashCode方法,除非将所有实例都设为具有相同的哈希码。


谢谢。那很有道理。 - mkohram
2
@mkohram 扩展 HashSet 从来不 是正确的做法,特别是如果您正在更改现有方法的行为。 - Andy Turner
另外,我不会改变行为。只是在HashSet<String>中添加了add(MyObject o)contains(MyObject o) - mkohram
3
在一个假装是HashSet或者Set的东西里,你不应该这样抽象化。 Set只应该反映equals行为,而且是正确、符合合同的equals行为。 - Louis Wasserman
4
或者创建一个自己的类来执行这些操作,但不要假装它是一个集合。 - Louis Wasserman
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接