Java PriorityQueue删除任意元素的性能

Java PriorityQueue删除任意元素的性能,java,performance,collections,queue,Java,Performance,Collections,Queue,假设我有一个java PriorityQueue(java实现为一个堆),我根据一些条件迭代它以删除元素: PriorityQueue q = new PriorityQueue(); ... Iterator it = q.iterator(); while(it.hasNext()){ if( someCriterion(it.next()) ) it.remove(); } 每个remove()操作需要多长时间?我不确定它是O(log(n))还是O(1)。如果您使

假设我有一个java PriorityQueue(java实现为一个堆),我根据一些条件迭代它以删除元素:

PriorityQueue q = new PriorityQueue();
...
Iterator it = q.iterator();
while(it.hasNext()){
    if( someCriterion(it.next()) )
        it.remove();
}
每个remove()操作需要多长时间?我不确定它是O(log(n))还是O(1)。

如果您使用的是Sun实现,那么它是
O(log(n))
。从:

实现说明:此实现提供 O(log(n))用于搜索和搜索方法的时间 (
提供
投票
删除()
添加
);
删除(对象)
包含(对象)
方法;和检索方法的恒定时间 (
peek
element
size

其他实现可能具有不同的复杂性


编辑:Javadocs没有涵盖使用迭代器删除元素的性能,因此我必须查找源代码。这一切都与Sun的实现有关,可能在苹果的版本、GNU类路径等方面有所不同。Sun的源代码是可用的;它也包含在JDK中,因此您可能已经安装了它

PriorityQueue
的迭代器中,
remove()
的默认情况是调用
PriorityQueue.removeAt(lastRet)
,其中
lastRet
next()
上次返回的索引
removeAt()
似乎是
O(log(n))
最坏的情况(它可能必须筛选队列,但不必迭代)

然而,有时坏事会发生。从
removeAt()
的注释中:

removeAt()
返回非空元素时,迭代器将其添加到一个特殊队列中供以后使用:当迭代器用完队列中的元素时,它将遍历这个特殊队列。在迭代的第二阶段调用
remove()
时,迭代器调用
PriorityQueue.removeq(lastRetElt)
,其中
lastRetElt
是从特殊队列返回的最后一个元素
removeq
被迫使用线性搜索来查找要删除的正确元素,这使得它
O(n)
。但它可以使用
=
而不是
.equals()
检查元素,因此其常量因子低于
优先级队列。删除(对象)


因此,换句话说,使用迭代器进行删除在技术上是
O(n)
,但在实践中,它应该比
remove(Object)

快一点,因为它没有指定迭代器的remove()操作时间。移除头部肯定需要O(log(n)),但是移除其他元素呢?好问题。让我看看源头;它可能会使用
remove(Object)
,这将使它成为线性的。remove()使用indexOf(),因此它是线性的,详细解释请参见!如果PriorityQueue没有在O(logn)时间内执行插入和删除操作,这难道不会使PriorityQueue变得多余吗?
/**
 * Removes the ith element from queue.
 *
 * Normally this method leaves the elements at up to i-1,
 * inclusive, untouched.  Under these circumstances, it returns
 * null.  Occasionally, in order to maintain the heap invariant,
 * it must swap a later element of the list with one earlier than
 * i.  Under these circumstances, this method returns the element
 * that was previously at the end of the list and is now at some
 * position before i. This fact is used by iterator.remove so as to
 * avoid missing traversing elements.
 */