为啥 set.contains 不使用覆盖的 equals() 方法?
Posted
技术标签:
【中文标题】为啥 set.contains 不使用覆盖的 equals() 方法?【英文标题】: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。
我将不胜感激。
【问题讨论】:
你试过调试你的代码吗?HashSet
的set.contains
将与hashCode()
(第一个)进行比较,并且您的顶点v,w
和w,v
具有不同的哈希码。
@ElliottFrisch 这很有道理,你知道我怎样才能让他们拥有相同的哈希码吗?
你可以试试return v+w;
【参考方案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)
。
您应该更改您的哈希码实现,使其独立于v
和w
的顺序。一种方法是先对较小的进行哈希处理:
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);
【讨论】:
以上是关于为啥 set.contains 不使用覆盖的 equals() 方法?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 `if None.__eq__("a")` 似乎评估为 True(但不完全)?
元素存在但 `Set.contains(element)` 返回 false
为啥为 __eq__ 定义参数类型会引发 MyPy 类型错误?