Java的PriorityQueue底层基于最小堆,用数组模拟完全二叉树,通过下标关系(左=2i+1、右=2i+2、父=(i-1)/2)映射父子节点;offer()触发上浮、poll()触发下沉,时间复杂度均为O(log n);支持自然序或自定义Comparator,但非线程安全且不保证同优先级元素的FIFO顺序。

Java 的 PriorityQueue 底层用的是**最小堆(Min-Heap)**,通过数组模拟完全二叉树实现优先级调度——元素按自然顺序或自定义比较器排序,每次 poll() 取出堆顶(即当前最高优先级元素),插入新元素后自动调整结构维持堆序性。
堆结构如何用数组表示
不使用指针,而是靠下标关系映射父子节点:
- 根节点在索引 0
- 对于任意节点索引 i:
- 左子节点索引 = 2 * i + 1
- 右子节点索引 = 2 * i + 2
- 父节点索引 = (i - 1) / 2(整除)
- 数组始终是“紧凑”的,新增元素追加到末尾,再向上/向下调整位置
插入元素时怎么维护堆序性
调用 offer() 后,新元素先放在数组末尾,然后执行上浮(siftUp)操作:
- 比较它和父节点的优先级(默认小值优先,即父 ≤ 子)
- 若违反堆序(比如新元素比父小),就交换,继续和新的父节点比较
- 直到满足堆序,或到达根节点
- 时间复杂度:O(log n)
取出最高优先级元素怎么调整结构
调用 poll() 时:
立即学习“Java免费学习笔记(深入)”;
- 先取走堆顶(索引 0)元素
- 把最后一个元素移到堆顶位置
- 然后执行下沉(siftDown):
- 比较它与两个子节点,找出三者中优先级最高的那个(最小值)
- 若不是自己,就和该子节点交换
- 重复此过程,直到满足堆序或无子节点
- 时间复杂度:O(log n)
优先级怎么定义:自然序 or 自定义比较器
PriorityQueue 支持两种优先级逻辑:
- 元素实现
Comparable接口 → 按compareTo()结果排序(默认最小堆) - 构造时传入
Comparator→ 按其compare()方法定义大小关系 - 注意:如果要用最大堆,可传
Comparator.reverseOrder()或写(a, b) -> b.compareTo(a) - 内部所有比较都基于这个规则,决定谁该“上浮”或“下沉”
不复杂但容易忽略:PriorityQueue 不是线程安全的;它不保证相同优先级元素的处理顺序(即不保证 FIFO);遍历顺序不反映堆序,只有 poll()/peek() 才体现优先级调度本质。


















