🔥 本文深入剖析Java中的优先队列PriorityQueue,从堆的基本概念到源码实现原理,带你全面理解这个重要的数据结构。由于内容较多,分为上下两篇,本篇是上篇,主要讲解基础概念和源码分析。
📚 系列专栏推荐:

1. 优先队列基础
1.1 什么是优先队列?
想象你正在医院的急诊室。虽然病人按到达顺序排队,但突然来了一位急重症病人,医生会优先处理这位病人。这就是现实生活中的"优先队列":不是先来先服务,而是按照优先级处理。
1.1.1 与普通队列的区别
普通队列就像我们排队买奶茶:
- 先来的人先买
- 后来的人后买
- 严格遵循"先进先出"(FIFO)原则
而优先队列则像医院的急诊室:
- 不是先来先服务
- 而是按照事件的紧急程度
- 优先级高的先处理
- 优先级相同时,先来先服务
让我们用代码来直观感受一下区别:
// 普通队列
Queue<String> normalQueue = new LinkedList<>();
normalQueue.offer("小明");
normalQueue.offer("小红");
normalQueue.offer("小张");
// 处理顺序:小明 -> 小红 -> 小张
// 优先队列
PriorityQueue<Patient> emergencyRoom = new PriorityQueue<>((p1, p2) ->
p2.getEmergencyLevel() - p1.getEmergencyLevel());
emergencyRoom.offer(new Patient("小明", 1)); // 普通感冒
emergencyRoom.offer(new Patient("小红", 3)); // 高烧
emergencyRoom.offer(new Patient("小张", 2)); // 扭伤
// 处理顺序:小红(高烧) -> 小张(扭伤) -> 小明(感冒)
1.1.2 优先级的概念
优先级可以基于多种规则:
- 自然顺序
- 数字:越小越优先
- 字符串:字典序越小越优先
// 数字优先队列(小顶堆)
PriorityQueue<Integer> numbers = new PriorityQueue<>();
numbers.offer(3);
numbers.offer(1);
numbers.offer(2);
System.out.println(numbers.poll()); // 输出1
- 自定义顺序
- 根据业务需求定义优先级
- 通过Comparator实现自定义排序
// 工作任务队列(按优先级排序)
PriorityQueue<Task> taskQueue = new PriorityQueue<>((t1, t2) -> {
// 先比较优先级
if (t1.getPriority() != t2.getPriority()) {
return t2.getPriority() - t1.getPriority();
}
// 优先级相同,比较创建时间
return t1.getCreateTime().compareTo(t2.getCreateTime());
});
1.1.3 实际应用场景
优先队列在我们的日常生活和系统开发中随处可见:
- 操作系统的进程调度
- 高优先级进程优先获得CPU时间片
- 系统进程优先级高于用户进程
- 前台进程优先级高于后台进程
- 打印机任务队列
- 紧急文件优先打印
- 老板的文件优先级更高
- 大文件可能优先级较低
- 游戏排位匹配系统
class Player {
private String name;
private int ranking;
private long waitTime;
// ... 其他属性
}
PriorityQueue<Player> matchQueue = new PriorityQueue<>((p1, p2) -> {
// 等待时间越长,优先级越高
long timeDiff = p2.getWaitTime() - p1.getWaitTime();
if (timeDiff != 0) {
return (int)timeDiff;
}
// 等待时间相同,按照排位分数匹配
return Math.abs(p1.getRanking() - targetRanking) -
Math.abs(p2.getRanking() - targetRanking);
});
- 网络请求处理
- VIP用户请求优先处理
- 支付请求优先于查询请求
- 实时性要求高的请求优先
通过这些例子,我们可以看到优先队列的核心特点:
- 动态调整处理顺序
- 基于优先级的灵活排序
- 在插入时自动维护顺序
- 保证每次取出的都是当前最优先的元素
理解了优先队列的本质,我们就能更好地在实际开发中运用它,设计出更合理的系统。接下来,我们将深入探讨它的底层实现原理——堆数据结构。
1.2 底层数据结构:堆
要理解优先队列,我们必须先理解它的底层数据结构——堆。想象一个公司的组织架构:CEO在最顶端,下面是经理,再下面是普通员工。堆的结构也是类似的层级关系。
1.2.1 什么是堆?
堆是一种特殊的完全二叉树,它满足以下特性:
- 结构性:是一个完全二叉树
- 有序性:任意节点的值总是大于(或小于)其子节点的值
就像公司架构:
- 完全二叉树:每层都尽可能填满,新人从左到右依次加入
- 有序性:职级高的总是在上层(类比大顶堆)
1.2.2 最大堆vs最小堆
- 最大堆(大顶堆)
- 父节点的值总是大于或等于子节点
- 堆顶是最大元素
// 最大堆示例
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
maxHeap.offer(1);
maxHeap.offer

最低0.47元/天 解锁文章
335

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



