【问题标题】:Why is set.contains not using overriden equals() method?为什么 set.contains 不使用覆盖的 equals() 方法?
【发布时间】:2020-04-11 17:37:03
【问题描述】:

我有这样的课:

class Vertex {
    char v;
    char w;
    int cost;

    public Vertex(char v, char w, int cost){
        this.v = v;
        this.w = w;
        this.cost = cost;
    }

    @Override
    public String toString(){
        return "["+v+" "+w+" "+cost+"]";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Vertex vertex = (Vertex) o;
        return (v == vertex.v && w == vertex.w) || (w == vertex.v && v == vertex.w);
    }

    @Override
    public int hashCode() {
        return Objects.hash(v, w);
    }
}

我试图让equals() 在两个顶点相等或相反相等时返回 true。这意味着如果存在顶点 (v,w) 和 (w,v),它应该返回 true。

我的equals() 应该是对称和自反的,但对于 (v,w) 和 (w,v) 情况,set.contains() 仍然返回 false。

我将不胜感激。

【问题讨论】:

  • 你试过调试你的代码吗?
  • HashSetset.contains 将与hashCode()(第一个)进行比较,并且您的顶点v,ww,v 具有不同的哈希码。
  • @ElliottFrisch 这很有道理,你知道我怎样才能让他们拥有相同的哈希码吗?
  • 你可以试试return v+w;

标签: java set equals contains hashset


【解决方案1】:

您的班级违反了hashCode() 的一般合同,而不是equals()Set.contains() 使用 hashCode() 来实现 O(1) 时间。

hashCode() 的通用合同规定相等的对象必须具有相等的哈希码。但是,在您的情况下,[v=1, w=2][v=2, w=1] 被认为是相等的,但它们具有不同的哈希码。你会分别打电话给Objects.hash(1, 2)Objects.hash(2, 1)

您应该更改您的哈希码实现,使其独立于vw 的顺序。一种方法是先对较小的进行哈希处理:

return Objects.hash(Math.min(v, w), Math.max(v, w));

【讨论】:

    【解决方案2】:

    正如@Sweeper 所写,您的 hashCode 应该以任何参数顺序返回相同的值,因此您可以返回参数的总和 hashCode:

    @Override
    public int hashCode() {
        return Objects.hashCode(v) + Objects.hashCode(w);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-05
      • 2014-05-27
      • 1970-01-01
      • 1970-01-01
      • 2012-06-22
      • 2014-03-19
      • 2011-04-17
      相关资源
      最近更新 更多