本文目录导读:

在 Java 中,优先队列(PriorityQueue)是 java.util 包下的一个类,它是一个基于优先级堆(默认是最小堆)的无界队列,下面我会从基础用法到高级用法(自定义排序)来详细讲解。
创建 PriorityQueue
默认(最小堆)
默认情况下,PriorityQueue 按元素的自然顺序排序(升序,即最小的元素最先出队)。
import java.util.PriorityQueue; PriorityQueue<Integer> pq = new PriorityQueue<>();
指定初始容量
PriorityQueue<Integer> pq = new PriorityQueue<>(10);
自定义比较器
当你想改变排序规则时,可以传入一个 Comparator。
示例1:最大堆(降序)
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
或者使用 Comparator.reverseOrder():
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
示例2:按字符串长度排序
PriorityQueue<String> pq = new PriorityQueue<>((s1, s2) -> s1.length() - s2.length());
常用方法
| 方法 | 说明 |
|---|---|
add(e) / offer(e) |
插入元素(offer 在容量限制时返回 false,无界队列时等价) |
peek() |
获取队首元素(不移除,队列为空返回 null) |
poll() |
获取并移除队首元素(队列为空返回 null) |
remove(e) |
移除指定元素(如果存在) |
size() |
返回元素个数 |
isEmpty() |
判断是否为空 |
clear() |
清空队列 |
toArray() |
转为数组(不保证有序) |
完整示例:最小堆
import java.util.PriorityQueue;
public class Example {
public static void main(String[] args) {
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
minHeap.add(5);
minHeap.add(1);
minHeap.add(8);
minHeap.add(3);
System.out.println("队首元素(最小):" + minHeap.peek()); // 1
while (!minHeap.isEmpty()) {
System.out.print(minHeap.poll() + " "); // 1 3 5 8
}
}
}
自定义对象优先级
假设你有一个 Task 类,希望按优先级(priority 字段)升序排列。
方法A:实现 Comparable 接口
class Task implements Comparable<Task> {
String name;
int priority;
Task(String name, int priority) {
this.name = name;
this.priority = priority;
}
@Override
public int compareTo(Task other) {
return Integer.compare(this.priority, other.priority); // 升序
}
@Override
public String toString() {
return name + "(" + priority + ")";
}
}
// 使用
PriorityQueue<Task> pq = new PriorityQueue<>();
pq.add(new Task("工作A", 3));
pq.add(new Task("工作B", 1));
pq.add(new Task("工作C", 2));
while (!pq.isEmpty()) {
System.out.println(pq.poll()); // 工作B(1), 工作C(2), 工作A(3)
}
方法B:传入 Comparator(推荐,更灵活)
class Task {
String name;
int priority;
Task(String name, int priority) {
this.name = name;
this.priority = priority;
}
public String toString() {
return name + "(" + priority + ")";
}
}
// 使用
PriorityQueue<Task> pq = new PriorityQueue<>((t1, t2) -> t1.priority - t2.priority);
// 或
// PriorityQueue<Task> pq = new PriorityQueue<>(Comparator.comparingInt(t -> t.priority));
pq.add(new Task("工作A", 3));
pq.add(new Task("工作B", 1));
pq.add(new Task("工作C", 2));
while (!pq.isEmpty()) {
System.out.println(pq.poll()); // 工作B(1), 工作C(2), 工作A(3)
}
重要注意事项
- 非线程安全:多线程环境需使用
PriorityBlockingQueue。 - 队列顺序 ≠ 遍历顺序:
iterator()返回的元素不保证有序。for (Integer x : pq) { // 可能不是有序的 }正确遍历方式是不断
poll()。 - 元素必须可比较:如果不提供
Comparator,元素必须实现Comparable,否则会抛ClassCastException。 - 不允许 null 元素。
| 场景 | 如何实现 |
|---|---|
| 最小堆(默认) | new PriorityQueue<>() |
| 最大堆 | new PriorityQueue<>(Comparator.reverseOrder()) |
| 自定义对象升序 | new PriorityQueue<>((a,b) -> a.field - b.field) 或 实现 Comparable |
| 自定义对象降序 | 交换比较顺序或使用 Comparator.comparing(T::getField).reversed() |
优先队列在解决“Top K 问题”、“合并多个有序链表”、“Dijkstra 最短路径”等场景中非常常用,掌握这些 API 用法就足够应对日常开发了。