为什么set.contains不使用重写equals()方法?

时间:2019-12-19 06:33:00

标签: java set equals contains hashset

我有一个这样的班级:

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()是对称且自反的,但是set.contains()对于(v,w)和(w,v)情况仍然返回false。

我将不胜感激。

2 个答案:

答案 0 :(得分: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));

答案 1 :(得分:1)

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

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