Java PriorityQueue 基于优先级堆实现,并非简单 FIFO 队列。元素按自然序或指定 Comparator 排序,队首始终为当前优先级最高(最小堆)或最低(最大堆)元素。插入 (offer/add) 和删除队首 (poll/remove) 操作时间复杂度为 O(log n),检索队首 (peek/element) 为 O(1)。其核心价值在于高效动态排序:新元素入队自动调整堆结构,确保队首最优。特别适用于任务调度(优先处理高优先级)、求 Top K 问题(维护 K 个元素的小顶堆)、Huffman 编码、图算法(如 Dijkstra)等场景。需注意:非线程安全;迭代顺序不保证完全有序(仅队首最优);允许 null 时需谨慎比较行为。
一、PriorityQueue 核心机制:堆的力量
PriorityQueue 底层通过二叉堆(通常是小顶堆) 实现。堆是一种部分有序的完全二叉树,满足:父节点值 <= 子节点值(小顶堆)。这种结构保证了:
- 队首元素(堆顶) 始终是当前队列中优先级最高(值最小)的元素。
- 插入/删除 操作通过“上浮”(siftUp)和“下沉”(siftDown)维护堆结构,时间复杂度为 O(log n),远优于每次全排序 (O(n log n))。
二、灵活排序:自然序 vs. 自定义 Comparator
自然排序: 元素需实现 Comparable 接口(如 Integer, String)。
PriorityQueue<Integer> minHeap = new PriorityQueue<>(); // 默认小顶堆
minHeap.offer(5); minHeap.offer(1); minHeap.offer(3);
System.out.println(minHeap.poll()); // 1 (最小)
定制排序: 通过 Comparator 指定复杂排序逻辑。
// 大顶堆:按字符串长度降序
PriorityQueue<String> maxHeap = new PriorityQueue<>(
(a, b) -> b.length() - a.length() // Lambda 定义 Comparator
);
maxHeap.offer("Apple"); maxHeap.offer("Pear"); maxHeap.offer("Banana");
System.out.println(maxHeap.poll()); // "Banana" (最长)
三、典型应用场景与示例
场景 1:高效处理 Top K 问题
问题: 从海量数据中找出最大的 K 个元素。
方案: 使用大小为 K 的小顶堆。新元素若大于堆顶,则替换堆顶并调整堆。
public List<Integer> topK(int[] nums, int k) {
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for (int num : nums) {
minHeap.offer(num);
if (minHeap.size() > k) minHeap.poll(); // 移除最小元素,保持堆大小为 K
}
return new ArrayList<>(minHeap); // 堆中即为最大的 K 个元素
}
场景 2:任务调度系统
需求: 优先执行高优先级任务。
方案: 使用 PriorityQueue 存储任务,按优先级排序。
class Task {
String name;
int priority; // 数值越大优先级越高
// Constructor, getters...
}
PriorityQueue<Task> taskQueue = new PriorityQueue<>(
(t1, t2) -> t2.priority - t1.priority // 大顶堆:按优先级降序
);
taskQueue.offer(new Task("Backup", 2));
taskQueue.offer(new Task("Urgent Bug Fix", 5));
taskQueue.offer(new Task("Report", 1));
while (!taskQueue.isEmpty()) {
Task next = taskQueue.poll();
System.out.println("Executing: " + next.name); // 先执行 "Urgent Bug Fix"
}
四、关键注意事项
- 非线程安全: 多线程环境需用
PriorityBlockingQueue。 - 迭代无序:
iterator()或toString()遍历不保证全局有序,仅poll()按序取出。 null值: 若允许null,需确保Comparator能处理,否则抛NullPointerException。- 性能: 插入删除 O(log n),检索队首 O(1)。初始容量不足时自动扩容(代价较高)。
结语: PriorityQueue 是处理动态优先级排序场景的利器。深入理解其堆实现原理与 Comparator 的灵活运用,能显著提升涉及优先级管理的算法与系统设计效率。善用此结构,可让程序在处理有序数据流时事半功倍。
855

被折叠的 条评论
为什么被折叠?



