【问题标题】:HashSet adds duplicate objects [duplicate]HashSet 添加重复对象 [重复]
【发布时间】:2013-06-07 08:58:37
【问题描述】:

我有一个 HashSet,它在图表中存储一些边。 每个 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;
    }

【问题讨论】:

  • 你是如何实现equals()和hashCode()的?
  • 您是否为Node 覆盖了equals 方法?
  • @Sam .equals() 单独是不够的,你还必须实现.hashCode();否则你会违反Object 合同。
  • @fge 显然是我的第二个问题
  • @veote .equals() 单独是不够的。当您覆盖 .equals() 时,您必须覆盖 .hashCode()。正如我已经说过的,这是Object 合约,是所有Java 中最基本的合约。

标签: java set hashcode


【解决方案1】:

如 cmets 中所述...

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

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

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

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

而这显然不是你想要的!

【讨论】:

    【解决方案2】:

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

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

    知道为什么

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-20
      • 2013-02-09
      相关资源
      最近更新 更多