2015-04-04 57 views
2

我保持Node对象在一个TreeSet:TreeSet包含/删除不工作?

public TreeSet<Node> viewNodes = new TreeSet<Node>(); 

节点看起来是这样的:

public class Node implements Comparable<Node>{ 
    private long nodeID; 
    ... 
    public long getID() { 
     return nodeID; 
    } 

    @Override 
    public int compareTo(Node n) { 
     System.out.println("comparing: " +this + " with " + n + " -- " + new Long(nodeID).compareTo(n.getID())); 
     return new Long(nodeID).compareTo(n.getID()); 
    } 

    @Override 
    public boolean equals(Object o){ 
     if(o instanceof Node){ 
      System.out.println((compareTo((Node)o) == 0)); 
      return compareTo((Node)o) == 0; 
     } 
     return false; 
    } 

    @Override 
    public int hashCode(){ 
     return new Long(nodeID).hashCode(); 
    } 
} 

然而,当我尝试删除节点,他们没有得到去除,TreeSet的认为他们不在集合中!

删除代码:

System.out.println("removing " + node); 
    System.out.println("viewNodes: " + viewNodes); 
    System.out.println("contains node?: " + viewNodes.contains(node)); 
    viewNodes.remove(node); 
    System.out.println("now viewNodes looks like: " +viewNodes); 

输出:

removing 5 
viewNodes: [5, 4, 3, 2, 1] 
comparing: 5 with 2 -- 1 
comparing: 5 with 1 -- 1 
contains node?: false 
comparing: 5 with 2 -- 1 
comparing: 5 with 1 -- 1 
now viewNodes looks like: [5, 4, 3, 2, 1] 

这是为什么?我已经实现了Comparable,应该不是吗?

+2

请显示一个小程序来演示问题。这个对我有用。 – 2015-04-04 22:18:20

+0

检查删除操作的结果。另请参阅包含()在预期删除后说的内容。你确认_node_被插入到容器中了吗?注意到你的输出说节点不包含这可能解释你看到的结果。 – bvj 2015-04-04 22:23:07

+0

将ID插入TreeSet后,我改变了它的值!它现在有用,谢谢你安迪!作为回答发布了 – Casey 2015-04-04 22:28:01

回答

0

正如Andy所说,我在将ID插入TreeSet后改变了ID的值。我想这导致节点得到错误排序。

现在有用,谢谢!

+0

。 – 2015-04-04 22:38:49

2

正如Andy所想的那样,您的问题在于您在插入后更改了元素的ID。

当使用任何类型的Set时,您应该注意不要在设置中更改元素。从Set interface documentation

注意:如果将可变对象用作set元素,必须非常小心。如果对象的值以影响等于比较的方式更改,而对象是集合中的元素,则不会指定集的行为。

同样的事情适用于Map键,您会在Map interface documentation中找到等价的语句。

在TreeSet(及其使用的底层TreeMap)中,使用compareTo方法的结果放置并稍后查找元素。如果compareTo的结果在插入和查找之间发生了变化,它可能无法正常工作。