Java PriorityQueue
当对象需要根据优先级被处理时,就会用到PriorityQueue。众所周知,队列遵循先入先出的算法,但有时需要根据优先级来处理队列中的元素,这时PriorityQueue就发挥作用了。
PriorityQueue是基于优先级堆的。优先级队列的元素根据自然排序,或者通过队列构造时提供的比较器进行排序,这取决于使用的构造器。
在下面的优先级队列中,具有最大ASCII值的元素将具有最高优先级。
声明
public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable
where E is the type of elements held in this queue
该类实现了 Serializable , **Iterable
关于优先级队列的 几个要点如下。
- PriorityQueue不允许出现null。
- 我们不能创建一个没有可比性的对象的PriorityQueue。
- PriorityQueue是非绑定队列。
- 这个队列的头部是相对于指定的排序而言的最小元素。如果多个元素在最小值上并列,那么头部就是这些元素中的一个–并列关系被任意打破。
- 由于PriorityQueue不是线程安全的,java提供了PriorityBlockingQueue类,实现了BlockingQueue接口,可以在java多线程环境中使用。
- 队列检索操作轮询、删除、窥视和元素访问队列头部的元素。
- 它为添加和轮询方法提供了O(log(n))时间。
- 它继承了 AbstractQueue 、 AbstractCollection 、 Collection 和 Object 类的方法。
构造函数
1.PriorityQueue(): 创建一个具有默认初始容量(11)的PriorityQueue,根据元素的自然排序进行排序。
PriorityQueue
**2.PriorityQueue(Collection
PriorityQueue<E> pq = new PriorityQueue<E>(Collection<E> c)
3.PriorityQueue(int initialCapacity) : 创建一个具有指定初始容量的PriorityQueue,根据其元素的自然顺序排列。
PriorityQueue<E> pq = new PriorityQueue<E>(int initialCapacity)
**4.PriorityQueue(int initialCapacity, Comparator
PriorityQueue<E> pq = new PriorityQueue(int initialCapacity, Comparator<E> comparator)
**5.PriorityQueue(PriorityQueue
PriorityQueue<E> pq = new PriorityQueue(PriorityQueue<E> c)
**6.PriorityQueue(SortedSet
PriorityQueue<E> pq = new PriorityQueue<E>(SortedSet<E> c)
例子
下面的例子解释了优先级队列的以下基本操作。
- boolean add(E element)。 这个方法将指定的元素插入到这个优先级队列中。
- public peek(): 这个方法检索,但不删除这个队列的头部,如果这个队列是空的,则返回null。
- public poll(): 这个方法检索并删除这个队列的头部,如果这个队列是空的,则返回null。
// Java program to demonstrate the
// working of PriorityQueue
import java.util.*;
class PriorityQueueDemo {
// Main Method
public static void main(String args[])
{
// Creating empty priority queue
PriorityQueue<Integer> pQueue = new PriorityQueue<Integer>();
// Adding items to the pQueue using add()
pQueue.add(10);
pQueue.add(20);
pQueue.add(15);
// Printing the top element of PriorityQueue
System.out.println(pQueue.peek());
// Printing the top element and removing it
// from the PriorityQueue container
System.out.println(pQueue.poll());
// Printing the top element again
System.out.println(pQueue.peek());
}
}
输出
10
10
15
对PriorityQueue的操作
让我们看看如何对优先级队列类进行一些常用的操作。
1.添加元素: 为了在优先级队列中添加一个元素,我们可以使用add()方法。在优先级队列中不保留插入顺序。元素是根据优先级顺序存储的,默认是升序。
/*package whatever //do not write package name here */
import java.util.*;
import java.io.*;
public class PriorityQueueDemo {
public static void main(String args[])
{
PriorityQueue<Integer> pq = new PriorityQueue<>();
for(int i=0;i<3;i++){
pq.add(i);
pq.add(1);
}
System.out.println(pq);
}
}
输出
[0, 1, 1, 1, 2, 1]
我们不会通过打印PriorityQueue获得排序的元素。
/*package whatever //do not write package name here */
import java.util.*;
import java.io.*;
public class PriorityQueueDemo {
public static void main(String args[])
{
PriorityQueue<String> pq = new PriorityQueue<>();
pq.add("Geeks");
pq.add("For");
pq.add("Geeks");
System.out.println(pq);
}
}
输出
[For, Geeks, Geeks]
2.删除元素: 为了从优先级队列中删除一个元素,我们可以使用remove()方法。如果有多个这样的对象,那么第一个出现的对象会被删除。除此以外,poll()方法也被用来删除头部并返回。
// Java program to remove elements
// from a PriorityQueue
import java.util.*;
import java.io.*;
public class PriorityQueueDemo {
public static void main(String args[])
{
PriorityQueue<String> pq = new PriorityQueue<>();
pq.add("Geeks");
pq.add("For");
pq.add("Geeks");
System.out.println("Initial PriorityQueue " + pq);
// using the method
pq.remove("Geeks");
System.out.println("After Remove - " + pq);
System.out.println("Poll Method - " + pq.poll());
System.out.println("Final PriorityQueue - " + pq);
}
}
输出
Initial PriorityQueue [For, Geeks, Geeks]
After Remove - [For, Geeks]
Poll Method - For
Final PriorityQueue - [Geeks]
3.访问元素: 由于队列遵循先入先出原则,我们只能访问队列的头部。要访问优先队列中的元素,我们可以使用peek()方法。
// Java program to access elements
// from a PriorityQueue
import java.util.*;
class PriorityQueueDemo {
// Main Method
public static void main(String[] args)
{
// Creating a priority queue
PriorityQueue<String> pq = new PriorityQueue<>();
pq.add("Geeks");
pq.add("For");
pq.add("Geeks");
System.out.println("PriorityQueue: " + pq);
// Using the peek() method
String element = pq.peek();
System.out.println("Accessed Element: " + element);
}
}
输出
PriorityQueue: [For, Geeks, Geeks]
Accessed Element: For
4.迭代PriorityQueue: 有多种方法可以迭代PriorityQueue。最著名的方法是将队列转换为数组并使用for循环进行遍历。然而,队列也有一个内置的迭代器,可以用来遍历队列。
// Java program to iterate elements
// to a PriorityQueue
import java.util.*;
public class PriorityQueueDemo {
// Main Method
public static void main(String args[])
{
PriorityQueue<String> pq = new PriorityQueue<>();
pq.add("Geeks");
pq.add("For");
pq.add("Geeks");
Iterator iterator = pq.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
}
}
输出
For Geeks Geeks
PriorityQueue类中的方法
方法 | 描述 |
---|---|
add(E e) | 将指定的元素插入到这个优先级队列中。 |
clear() | 删除这个优先级队列中的所有元素。 |
comparator() | 返回用于对这个队列中的元素进行排序的比较器,如果这个队列是按照其元素的自然排序的,则返回空。 |
contains(Object o) | 如果这个队列包含指定的元素,返回真。 |
forEach(Consumer super E> action) | 对Iterable的每个元素执行给定的动作,直到所有的元素都被处理完,或者该动作抛出一个异常。 iterator() | 返回这个队列中的元素的一个迭代器。 offer(E e) | 将指定的元素插入到这个优先级队列中。 remove(Object o) | 从这个队列中删除指定元素的一个实例,如果它存在的话。 removeAll(Collection> c) |
删除这个集合中也包含在指定集合中的所有元素(可选操作)。 |
removeIf(Predicate super E> filter) | 删除此集合中满足给定谓词的所有元素。 retainAll(Collection> c) |
只保留此集合中包含在指定集合中的元素(可选操作)。 |
spliterator() | 在这个队列中的元素上创建一个晚期绑定的、故障快速的Spliterator。 |
toArray() | 返回一个包含此队列中所有元素的数组。 |
toArray(T[] a) | 返回一个包含队列中所有元素的数组;返回的数组的运行时类型是指定数组的类型。 |
类java.util.AbstractQueue中声明的方法
方法 | 描述 |
---|---|
addAll(Collection extends E> c) | 将指定集合中的所有元素添加到这个队列中。 element() | 检索,但不删除这个队列的头部。 remove() | 检索并删除此队列的头部。 ### java.util.AbstractCollection类中声明的方法 方法 | 描述 |
如果这个集合包含了指定集合中的所有元素,则返回true。 |
isEmpty() | 如果这个集合不包含任何元素,则返回true。 |
toString() | 返回这个集合的字符串表示。 |
java.util.Collection接口中声明的方法
方法 | 描述 |
---|---|
containsAll(Collection<?> c) | 如果这个集合包含了指定集合中的所有元素,返回true。 |
equals(Object o) | 将指定的对象与这个集合进行比较,看是否相等。 |
hashCode() | 返回此集合的哈希代码值。 |
isEmpty() | 如果这个集合不包含任何元素,返回true。 |
parallelStream() | 返回一个以该集合为源的可能的并行流。 |
size() | 返回这个集合中元素的数量。 |
stream() | 返回一个以这个集合为源的顺序流。 |
toArray(IntFunction<T[]> generator) | 返回一个包含此集合中所有元素的数组,使用提供的生成器函数来分配返回的数组。 |
在接口java.util.Queue中声明的方法
方法 | 描述 |
---|---|
peek() | 检索但不删除该队列的头部,如果该队列为空,则返回null。 |
poll() | 检索并删除这个队列的头部,如果这个队列是空的,则返回null。 |
应用:
- 实现Dijkstra的和Prim的算法。
- 在K次否定后使数组总和最大化