一致的Equals()结果,但不一致的TreeMap.containsKey()结果

sme*_*ing 2 java equals hashcode treemap comparable

我有以下对象Node:

    private class Node implements Comparable<Node>(){
         private String guid();

         ...

         public boolean equals(Node o){
             return (this == o);
         }

         public int hashCode(){
              return guid.hashCode();
         }

         public int compareTo(Node o){
            return (this.hashCode() - o.hashCode());
         }

         ...

    }
Run Code Online (Sandbox Code Playgroud)

我在下面使用它TreeMap:

TreeMap<Node, TreeSet<Edge>> nodes = new TreeMap<Node, TreeSet<Edge>>();
Run Code Online (Sandbox Code Playgroud)

现在,树图被用在一个被调用的类中,Graph用于存储当前在图中的节点,以及它们的一组边(来自类Edge).我的问题是当我尝试执行时:

   public containsNode(n){
        for (Node x : nodes.keySet()) {
            System.out.println("HASH CODE: ");
            System.out.print(x.hashCode() == n.hashCode());
            System.out.println("EQUALS: ");
            System.out.print(x.equals(n));
            System.out.println("CONTAINS: ");
            System.out.print(nodes.containsKey(n));
            System.out.println("N: " + n);
            System.out.println("X: " + x);
            System.out.println("COMPARES: ");
            System.out.println(n.compareTo(x));
            }
        }
Run Code Online (Sandbox Code Playgroud)

我有时会得到以下内容:

HASHCODE:true EQUALS:true CONTAINS: false N:foo X:foo比较:0

任何人都知道我做错了什么?我对这一切hashCode()还不熟悉,所以如果我忽略了一些简单的事情TreeMap,我会事先道歉(我知道这并不重要,但我想我会把它包括在内).

edit1:添加compareTo()方法信息.

Eya*_*der 5

TreeSet不使用equals()来确定相等性.它使用Comparator(或Comparable)代替.为了使其正常工作,您必须遵循equals规则的一致性:

"当且仅当c.compare(e1,e2)== 0具有与e1.equals(e2)相同的布尔值时,比较器c对一组元素S施加的排序被认为与等于一致. S"中的e1和e2.

我猜你没有遵循这个规则(你没有提供compareTo方法的实现).如果未遵循规则,则树集将不具有Set的正常行为.

有关详细信息,请参阅http://eyalsch.wordpress.com/2009/11/23/comparators/.

- 编辑 -

现在您提供了compareTo实现,很明显它有一个缺陷.对于不相等的2个节点(并且具有相同的哈希码),它可以返回0.因此,您无法将具有相同哈希码的2个项添加到TreeSet中!


Tom*_*ine 5

这里有一些问题.

  • 你还没有覆盖Object.equals.使用@Override public boolean equals(Object obj).
  • 中有一个潜在的整数溢出错误compareTo.这可能是导致此特定错误的原因.它会扰乱排序,因此搜索可能不会成功.
  • compareTo方法声称如果哈希码恰好匹配,则两个实例是相等的(可能是难以捕获的错误,没有代码审查).

对于整数溢出问题,请参阅问题为什么我的简单比较器被破坏?

  • 作为对其他答案的评论,不同的guid并不意味着guid的不同哈希码.我认为这是导致问题的整数溢出. (4认同)