TreeSet包含/删除不起作用?

时间:2015-04-04 22:12:05

标签: java contains comparable treeset

我将Node对象保存在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 个答案:

答案 0 :(得分:2)

正如安迪想的那样,你的问题是你在插入后更改了元素的ID。

当使用任何类型的Set时,您应该注意不要在它们位于Set中时更改元素。来自Set interface documentation

  

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

同样的事情适用于Map键,你会在Map interface documentation中找到一个等效语句。

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

答案 1 :(得分:0)

在将其插入TreeSet之后,我正在更改ID的值,正如Andy建议的那样。我想这会导致节点排序不正确。

现在有效,谢谢!