PriorityQueue 是 Java 中的一个类,它实现了一个基于优先级的队列,允许元素按照指定的优先级进行处理。常见的应用场景包括任务调度、图的最短路径算法、合并有序数据等。以下是关于 PriorityQueue 一些常见的知识点:
1. 基本特性
PriorityQueue是一个无界的队列,默认情况下,它是按照自然顺序(Comparable接口)进行排序的。如果元素是自定义对象,可以通过提供一个Comparator来定义排序规则。- 它实现了
Queue接口,因此支持常见的队列操作,例如add(),poll(),peek()等。 - 元素是根据优先级顺序出队的,而不是入队的顺序。
2. 构造方法
PriorityQueue 提供了多个构造函数,常见的有:
- 默认构造方法:根据元素的自然顺序进行排序。
PriorityQueue<Integer> pq = new PriorityQueue<>(); - 自定义排序规则:通过
Comparator提供自定义排序顺序。PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder()); - 初始容量和比较器:指定初始容量和排序规则。
PriorityQueue<Integer> pq = new PriorityQueue<>(50, Comparator.naturalOrder());
3. 基本操作
add(E e):向队列添加元素。如果元素成功添加,返回true,如果队列已满,则抛出异常。offer(E e):向队列添加元素。如果元素添加成功,返回true,否则返回false(适用于有界队列的情况)。poll():移除并返回队头元素,返回null如果队列为空。peek():返回队头元素,但不移除它,返回null如果队列为空。size():返回队列中元素的个数。isEmpty():检查队列是否为空。
4. 排序
- 初始容量和比较器:指定初始容量和排序规则。
PriorityQueue<Integer> pq = new PriorityQueue<>(50, Comparator.naturalOrder()); - 默认情况下,
PriorityQueue使用元素的自然顺序进行排序(即元素必须实现Comparable接口)。例如,对于Integer类型,队列会按升序排列。 -
PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder()); - 🤣如果要按照自定义规则排序,可以传入一个
Comparator,例如: -
PriorityQueue<long[]> queue = new PriorityQueue<>(((o1, o2) -> { if (o1[0] == o2[0]) return Long.compare(o1[1], o2[1]); else return Long.compare(o1[0], o2[0]); })); -
这里创建了一个优先队列,用来存储每个数组元素及其对应的索引。队列中的每个元素是一个
long[]数组,其中o1[0]和o2[0]是数组中的值,o1[1]和o2[1]是对应的索引。排序规则是:首先按照数组元素的值进行升序排序,如果值相等,则按照索引升序排序。
5. 访问队头元素
PriorityQueue始终保证队头是优先级最高的元素(即最小的元素,或者最大,取决于比较器)。- 如果使用默认的比较器,队头元素是最小的。
PriorityQueue<Integer> pq = new PriorityQueue<>(); pq.add(3); pq.add(1); pq.add(2); System.out.println(pq.peek()); // 输出 1,因为 1 是最小的元素
6. 效率
- 插入操作(
add())和删除操作(poll())的时间复杂度为 O(log n),其中n是队列中元素的数量。 - 获取队头元素(
peek())的时间复杂度是 O(1)。
7. 应用场景
- 任务调度:可以用来按优先级调度任务,最小堆或最大堆可以表示任务的优先级。
- 合并有序数据:例如合并多个有序文件时,可以使用
PriorityQueue来动态获取当前最小的元素。 - 图算法:例如 Dijkstra 最短路径算法中使用优先队列来获取当前最短路径的节点。
8. 最大堆与最小堆
- 默认情况下,
PriorityQueue是最小堆,即优先级最高的元素在队头(值最小的元素在队头)。 - 如果需要最大堆(即优先级最高的元素是值最大的),可以提供一个反向的比较器(
Comparator.reverseOrder()):PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());
9. 线程安全
PriorityQueue 不是线程安全的。如果需要在多线程环境中使用,可以通过 Collections.synchronizedQueue 或使用 ConcurrentLinkedQueue 来保证线程安全,或者使用 PriorityBlockingQueue 来实现线程安全的优先级队列。
10. 队列的清空
clear():清空队列中的所有元素。pq.clear();
浙公网安备 33010602011771号