HashSet添加重复的对象

时间:2013-06-07 08:58:38

标签: java set hashcode

我有一个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;
    }

2 个答案:

答案 0 :(得分:5)

如评论中所述......

您必须为BOTH课程.equals().hashCode()实施EdgeNode

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

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

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

这显然不是你想要的!

答案 1 :(得分:1)

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

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

知道原因