使用PriorityQueue删除意外行为:为什么不使用compareTo?

时间:2012-01-18 07:44:34

标签: java equals priority-queue compareto

我正在尝试使用优先级队列,但remove()不起作用: 我的代码:

PriorityQueue<OwnClass> pq=new PriorityQueue<OwnClass>();
OwnClass a=new OwnClass(1);
OwnClass b=new OwnClass(2);
OwnClass c=new OwnClass(3);
pq.add(a);
pq.add(b);
pq.add(c);
System.out.println("head:"+pq.peek());
pq.remove(new OwnClass(1));
System.out.println(pq.peek());

类实现:

class OwnClass implements Comparable{

    int x;

    public OwnClass(int x){
        this.x=x;
    }

    public int compareTo(Object arg0) {

        OwnClass a=(OwnClass) arg0;
        if(a.x>this.x)
            return -1;
        if(a.x<x)
            return 1;
        return 0;
    }

    public String toString(){
        return ""+x;        
    }
}

我认为输出最终输出应为2,因为我删除了添加的'1'。 compareTo()应该由优先级队列remove()使用,但他的情况似乎并非如此。我做错了什么?我知道pq.remove(a)会起作用,但我的代码也可以工作

3 个答案:

答案 0 :(得分:8)

remove()不会使用compareTo(),而是使用equals()来查找要删除的对象。您还需要覆盖课程中的equals()

编辑:PriorityQueue {{1}}(谢谢,@ templatetypedef)

答案 1 :(得分:2)

PriorityQueue类的remove方法具有以下描述:

  

从此队列中删除指定元素的单个实例(如果存在)。 更正式地,如果此队列包含一个或多个此类元素,则删除元素e o.equals(e)当且仅当此队列包含指定元素时返回true(或等效,如果这样队列因调用而改变了。

因此,在确定是否compareTo时,不会使用remove。我认为这是因为PriorityQueue实现了Collection,因此remove的行为必须与Collection中指定的行为一致,即

  

从此集合中移除指定元素的单个实例(如果存在)(可选操作)。 更正式地,如果此集合包含一个或多个此类元素,则删除元素e(o == null?e == null:o.equals(e))。

换句话说,我相信这个设计决策的动机是试图让PriorityQueue适应Collection框架,即使它有点奇怪。

希望这有帮助!

答案 2 :(得分:2)

请注意,PriorityQueue还有一个带有Comparator的构造函数。 因此,即使使用了Comparator或者priorityQueue中的对象实现了Comparable Interface,也可以保持remove行为的一致性,equals不依赖于除了Object的base equals属性之外的任何比较。