Java优先队列API如何用

wen java案例 1

本文目录导读:

Java优先队列API如何用

  1. 创建 PriorityQueue
  2. 常用方法
  3. 完整示例:最小堆
  4. 自定义对象优先级
  5. 重要注意事项

在 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)
}

重要注意事项

  1. 非线程安全:多线程环境需使用 PriorityBlockingQueue
  2. 队列顺序 ≠ 遍历顺序iterator() 返回的元素不保证有序。
    for (Integer x : pq) {
        // 可能不是有序的
    }

    正确遍历方式是不断 poll()

  3. 元素必须可比较:如果不提供 Comparator,元素必须实现 Comparable,否则会抛 ClassCastException
  4. 不允许 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 用法就足够应对日常开发了。

抱歉,评论功能暂时关闭!