本文目录导读:

在 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 用法就足够应对日常开发了。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播