我有一个HashSet,它在Graph中存储了一些边。 每个Edge都有两个节点。
如果图表是无向的,添加副本应该会失败:
Edge a = new Edge(new Node("aa"), new Node("bb"));
Edge duplicate = new Edge(new Node("aa"), new Node("bb"));
但是在下面的例子中它起作用:
System.out.println(a.equals(duplicate));
Set<Edge> sete = new HashSet<Edge>();
System.out.println(sete.contains(a));
System.out.println(sete.add(a));
System.out.println(sete.contains(duplicate));
System.out.println(sete.add(duplicate));
Output:
true
false
true
false
true
编辑: 好了,我现在添加了一个hashCode方法,适用于定向边。 有人可以帮我计算无向边的哈希吗?
public class Edge {
private Node first, second;
@Override
public /boolean equals(Object ob) {
if (ob instanceof Edge) {
Edge edge = (Edge) ob;
if (first.equals(edge.first)
&& second.equals(edge.second)
|| first.equals(edge.second)
&& second.equals(edge.first))
return true;
}
return false;
}
@Override
public int hashCode() {
int hash = 17;
int hashMultiplikator = 79;
hash = hashMultiplikator * hash
+ first.hashCode();
hash = hashMultiplikator * hash
+ second.hashCode();
return hash;
}
答案 0 :(得分:5)
如评论中所述......
您必须为BOTH课程.equals()
和.hashCode()
实施Edge
和Node
。
HashSet
使用.hashCode()
来确定放置新条目的哈希桶;如果此存储桶中已有条目,则会在存储桶的每个条目上使用.equals()
来查看该条目是否已存在。
由于您没有覆盖其中任何一个,因此这些方法的实现是Object
的一个:
.hashCode()
是对象引用地址的简单哈希值; .equals()
才为真(即o1 == o2
)。这显然不是你想要的!
答案 1 :(得分:1)
对此现象的唯一解释是Edge.hashCode不正确或未被覆盖。您应该将这些行添加到您的代码中
System.out.println(a.hashCode());
System.out.println(duplicate.hashCode());
知道原因