我们时不时地需要以特定的顺序处理队列中的项目。优先级队列是一种完成这项工作的数据结构。 Java优先级队列与“普通”不同queue。它不是“先进先出”,而是按优先级顺序检索项目。
The java.util.PriorityQueue
class, provides us an implementation of such a data type, by using priority heap implementation internally. Java PriorityQueue is an unbounded queue. It was introduced in Java 1.5 and enhanced in Java SE 8 release. PriorityQueue is internally implemented by following “Priority Heap” data structure. Here is the PriorityQueue class hierarchy: PriorityQueue Class Diagram:
-
优先队列()- 创建一个具有默认初始容量的 PriorityQueue,即 11
-
优先级队列(集合c)- 使用指定集合中的元素创建一个 PriorityQueue
-
PriorityQueue(int 初始容量)- 创建具有指定初始容量的 PriorityQueue
-
PriorityQueue(int initialCapacity, Comparator 比较器)- 使用提供的初始容量创建一个 PriorityQueue,其元素的顺序根据指定的比较器
-
优先队列(优先队列c)- 创建一个包含指定优先级队列中元素的 PriorityQueue
-
优先队列(SortedSet c)- 创建一个包含指定排序集中元素的 PriorityQueue
优先级队列元素按其自然顺序排序,除非我们提供Comparator在创建它的同时。默认情况下,元素按升序排列,因此队列的头部是优先级最低的元素。如果有两个元素同时有资格成为头部,那么这种联系就被任意打破。
让我们创建一个PriorityQueue
,包含各种任务:
PriorityQueue tasks=new PriorityQueue();
tasks.add("task1");
tasks.add("task4");
tasks.add("task3");
tasks.add("task2");
tasks.add("task5");
这将创建一个任务的 PriorityQueue,它将按任务的自然顺序进行排序String
。让我们创建另一个 PriorityQueue,它以与自然顺序相反的顺序对任务进行排序。所以我们需要传递一个比较器:
PriorityQueue reverseTasks=new PriorityQueue(Comparator.reverseOrder());
reverseTasks.add("task1");
reverseTasks.add("task4");
reverseTasks.add("task3");
reverseTasks.add("task2");
reverseTasks.add("task5");
现在,让我们看一下 PriorityQueue 的所有可用方法并使用它们:
-
布尔加法(E e)- 此方法将指定元素插入队列中。我们已经使用此方法在队列中添加了 5 个任务。
-
比较器 比较器()- 此方法返回用于对该队列中的元素进行排序的比较器。如果未指定比较器并且队列根据其元素的自然顺序进行排序,则返回 null。所以,如果我们这样做:
System.out.println(tasks.comparator());
System.out.println(reverseTasks.comparator());
输出将是:
null
java.util.Collections$ReverseComparator@15db9742
-
布尔值包含(对象o)- 如果队列包含指定元素,则返回 true。让我们检查“task3”是否属于优先级队列任务:
System.out.println(tasks.contains("task3"));
这打印:
true
-
布尔报价(E e)- 就像add()方法一样,该方法也向队列添加一个元素。对于容量受限的队列,offer() 和 add() 方法实际上有点不同,但对于 PriorityQueue,两者是相同的。与 add() 不同,offer() 即使未能将元素添加到队列中也不会抛出异常。
-
E peek()- 检索此队列的头部,如果此队列为空,则返回 null。换句话说,它返回具有最高优先级的元素。所以下面的代码:
System.out.println(tasks.peek());
System.out.println(reverseTasks.peek());
给我们:
task1
task5
-
E poll()- 此方法还检索队列的头部(具有最高优先级的元素),或者如果队列为空则返回 null。但与 peek() 不同的是,它还会删除该元素。因此,如果我们调用 poll():
System.out.println(“Poll on tasks: ”+tasks.poll());
System.out.println(“Poll on reverseTasks: ”+reverseTasks.poll());
然后看一下:
System.out.println(“Peek on tasks: ”+tasks.peek());
System.out.println(“Peek on reverseTasks: ”+reverseTasks.peek());
我们将得到以下输出:
Poll on tasks: task1
Poll on reverseTasks: task5
Peek on tasks: task2
Peek on reverseTasks: task4
-
整数大小()- 返回队列中元素的数量。
-
布尔删除(对象o)- 从队列中删除指定元素(如果存在)。如果存在两个相同的元素,则仅删除其中之一。
-
对象[] toArray()- 返回一个包含队列中所有元素的数组。
-
T[] toArray(T[] a)- 返回一个包含队列中所有元素的数组,返回数组的类型为指定数组的类型。
-
迭代器 迭代器()- 返回队列的迭代器。
-
无效清除()- 从队列中删除所有元素。
除了这些之外,PriorityQueue
还继承了方法Collection
and Object
类。
- 对于入队和出队方法,时间复杂度为 O(log(n))
- 对于remove(Object)和contains(Object)方法,时间复杂度是线性的
- 对于检索方法,具有恒定的时间复杂度
优先级队列的这种实现不是线程安全的。所以,如果我们需要同步访问,我们需要使用优先级阻塞队列。参考:API Doc
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)