我遇到了有关Java 8,Intellij Idea中PriorityQueue顺序的问题,当我在队列中添加第三个数字时,顺序是错误的,但是只有第三个有此问题,这是我的代码。
import java.util.*;
public class vector {
static Queue<Integer> q=new PriorityQueue<Integer>();
public static void addNum(int num) {
q.add(num);
}
public static void main(String args[]) {
addNum(-1);
addNum(-2);
addNum(-3);
addNum(-4);
addNum(-5);
}
}
我尝试调试代码,在addNum(-3)之后,队列是-3,-1,-2,但是在addNum(-4)之后,队列是-4,-3,-2,- 1。
答案 0 :(得分:5)
看来PriorityQueue
的合同并不一定保证 iteration 的顺序,而是保证从优先级队列中删除的每个元素都将遵循队列类型的自然顺序,或应提供自定义比较器的顺序。
Javadoc对您所看到的内容的评论:
通常(但不一定)以FIFO(先进先出)的方式对元素进行排序。例外情况包括优先级队列(根据提供的比较器对元素进行排序或元素的自然排序)和LIFO队列(或堆栈),对LIFO(后进先出)元素进行排序。
Java似乎对优先级队列强制执行的约定是,从队列中移除的第一个元素将遵循队列中对象的自然顺序,或者使用自定义比较器(如果是)提供。
如果我们添加到当前脚本中以删除添加的五个元素,我们将看到返回的项将按从小到大的顺序排列:
public static void main(String args[]) {
addNum(-1);
addNum(-2);
addNum(-3);
addNum(-4);
addNum(-5);
// now remove all elements
while (!q.isEmpty()) {
System.out.println(q.remove());
}
}
此打印:
-5
-4
-3
-2
-1
如果您需要一个保持排序顺序的集合,请考虑使用类似TreeSet
的东西。或者,可以使用常规的ArrayList
,然后如果想强加特定顺序,请致电Collections.sort()
。
答案 1 :(得分:0)
PriorityQueue的实现是优先级堆实现,而不是排序列表。
不保证方法iterator()中提供的Iterator以任何特定顺序遍历优先级队列的元素。如果您需要有序遍历,请使用以下内容:
Arrays.sort(q.toArray());
for (Integer data :q) {
System.out.println(data);
}
答案 2 :(得分:0)
正如其他答案所暗示的,如果您想以正确的顺序检索元素,您应该使用 queue.poll()
,例如:
List<E> entities = new ArrayList<>();
while(!queue.isEmpty()){
entities.add(queue.poll());
}
entities
列表中的实体顺序与预期一致。
基本原理:Java PriorityQueue
仅确保实体的入队顺序,而不是基础集合中的迭代顺序。
实体被映射到“未排序”的底层集合,这意味着如果您尝试使用流访问实体:
queue.stream().collect(Collectors.toList());
或迭代器:
Iterator<E> i = queue.iterator();
...
E e = i.next()
或任何其他方法,例如 queue.forEach()
,或者实际上在 IDE 调试器中观察您的队列,无法保证使用任何这些方法获得的集合中条目的顺序。>
答案 3 :(得分:-2)
这是最常见的问题,许多集合框架工作,如 ArrayList、LinkedList,但在 PriorityQueue 中,当您打印元素时,它将按排序顺序排列,并遵循该顺序 MIN_HEAP 属性 或 基本上,我们可以说优先队列是在最小堆属性上实现的。 所以先了解MinHeap然后实现代码。