如何迭代PriorityQueue?

sim*_*ico 30 java collections loops priority-queue

for (Event e : pq)
Run Code Online (Sandbox Code Playgroud)

不按优先级顺序迭代.

while(!pq.isEmpty()){
  Event e = pq.poll();
}
Run Code Online (Sandbox Code Playgroud)

这可以工作但排空队列.

Oli*_*rth 25

来自Javadocs:

方法中提供的迭代器iterator()不保证以任何特定顺序遍历PriorityQueue的元素.如果您需要有序遍历,请考虑使用Arrays.sort(pq.toArray()).

可能还有其他等效机制.

  • 这个答案将从一个例子中受益.`Arrays.sort(pq.toArray())`就我所知道的而言什么也没做.首先,必须创建一个包含`PriorityQueue`元素的数组,然后可以使用`Arrays.sort(theActualArray,pq.comparer())`对该数组进行排序. (7认同)

Ale*_*scu 25

由于底层实现,您无法按顺序遍历优先级队列(我认为它是Java中的min-heap).它不是一个排序数组,因此您可以从一个元素转到具有较低优先级的元素.偷看是恒定的时间,因为它看着最小的元素.要获得下一个(在O(log n)时间内),您必须将最小元素出列,这就是它的工作原理.Dequeing不仅仅是将该元素取出,底层结构重新排列,以便首先将元素放在最低优先级.

此外,遍历整个优先级队列的是O(n log(n))操作.所以你也可以抓住队列中的所有元素并对它们进行排序(也是O(n log(n))),然后你可以按照自己的意愿进行排序.唯一的缺点是你持有队列的额外副本.

尽管如此,如果您需要以这种方式遍历数据,优先级队列可能不是满足您需求的正确数据结构.

  • 完全没有,它非常有用,并且非常适合它实际意图做的事情.创建比完全排序的数据结构(线性与O(n log n))更快,但您仍然可以在常量时间内找到最小值/最大值并在log n中排队/出列.如果您需要在所有元素上按排序顺序迭代,那么它就不是正确的数据结构. (11认同)
  • 那么,`PriorityQueue` 几乎没用了? (2认同)
  • @Qix 并不总是迭代是一个糟糕的设计;OP 想要遍历所有元素,但有时我需要从优先级队列中找到匹配某个谓词的第一个元素。然后,对 10k 数组进行排序以获取前 10 个元素之一的效率非常低(尤其是在循环中完成时) (2认同)

Dil*_*nga 10

基于堆的优先级队列仅保证第一个元素是最高/最低.没有便宜的(即O(n))方式来获取排序形式的元素.

如果您需要经常这样做,请考虑使用以排序形式维护元素的结构.例如,使用java.util.TreeSet和使用pollFirst()pollLast()代替peek()/poll()


小智 6

之前的发帖者已经说了一切,但没有人给出完整的工作示例(除了复制 pq),所以这里是:

Event[] events = pq.toArray(new Event[pq.size()]);
Arrays.sort(events, pq.comparator());
for (Event e : events) {
    System.out.println(e);
}
Run Code Online (Sandbox Code Playgroud)