为什么 set.contains 不使用覆盖的 equals() 方法?
Why is set.contains not using overriden equals() method?
我有一个 class 这样的:
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()
return 为真。这意味着如果存在顶点 (v,w) 和 (w,v),它应该 return 为真。
我的 equals()
应该是对称的和自反的,但对于 (v,w) 和 (w,v) 的情况 set.contains()
return 仍然是错误的。
如有任何帮助,我将不胜感激。
您的 class 违反了 hashCode()
的一般合同,而不是 equals()
。 Set.contains()
使用 hashCode()
实现 O(1) 时间。
hashCode()
的一般契约规定相等的对象必须具有相等的哈希码。但是,在您的情况下, [v=1, w=2]
和 [v=2, w=1]
被认为是相等的,但它们具有不同的哈希码。您将分别调用 Objects.hash(1, 2)
和 Objects.hash(2, 1)
。
您应该更改哈希码实现,使其独立于 v
和 w
的顺序。一种方法是先散列较小的一个:
return Objects.hash(Math.min(v, w), Math.max(v, w));
正如@Sweeper 所写,您的 hashCode 应该 return 在任何参数顺序中具有相同的值,因此您可以 return 参数 hashCode 的总和:
@Override
public int hashCode() {
return Objects.hashCode(v) + Objects.hashCode(w);
}
我有一个 class 这样的:
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()
return 为真。这意味着如果存在顶点 (v,w) 和 (w,v),它应该 return 为真。
我的 equals()
应该是对称的和自反的,但对于 (v,w) 和 (w,v) 的情况 set.contains()
return 仍然是错误的。
如有任何帮助,我将不胜感激。
您的 class 违反了 hashCode()
的一般合同,而不是 equals()
。 Set.contains()
使用 hashCode()
实现 O(1) 时间。
hashCode()
的一般契约规定相等的对象必须具有相等的哈希码。但是,在您的情况下, [v=1, w=2]
和 [v=2, w=1]
被认为是相等的,但它们具有不同的哈希码。您将分别调用 Objects.hash(1, 2)
和 Objects.hash(2, 1)
。
您应该更改哈希码实现,使其独立于 v
和 w
的顺序。一种方法是先散列较小的一个:
return Objects.hash(Math.min(v, w), Math.max(v, w));
正如@Sweeper 所写,您的 hashCode 应该 return 在任何参数顺序中具有相同的值,因此您可以 return 参数 hashCode 的总和:
@Override
public int hashCode() {
return Objects.hashCode(v) + Objects.hashCode(w);
}