1

我有一个 HashSet,它在图中存储了一些边。每个边缘有两个节点。

在图是无向的情况下,添加副本应该会失败:

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;
    }
4

2 回答 2

5

正如评论中提到的......

您必须为两个类.equals()和..hashCode()EdgeNode

AHashSet用于.hashCode()确定放置新条目的哈希桶;如果此存储桶中已有条目,则在存储桶.equals()的每个条目上使用以查看该条目是否已存在。

由于您没有覆盖其中任何一个,因此这些方法的实现是以下之一Object

  • .hashCode()是对象引用地址的简单散列;
  • .equals()当且仅当两个对象是相同的引用(即o1 == o2)时才为真。

而这显然不是你想要的!

于 2013-06-07T09:02:00.273 回答
1

对此现象的唯一解释是 Edge.hashCode 不正确或未被覆盖。您应该已将这些行添加到您的代码中

System.out.println(a.hashCode());
System.out.println(duplicate.hashCode());

知道为什么

于 2013-06-07T09:04:22.347 回答