java中priorityqueue底层用最小堆实现,基于动态扩容的object数组,通过索引关系(左子2i+1、右子2i+2、父(i-1)/2)隐式维护完全二叉树结构;插入执行siftup上浮,删除执行siftdown下沉;支持comparator或comparable排序,不保证线程安全且不允许null元素。

PriorityQueue 在 Java 中底层用的是“最小堆”(Min-Heap),基于动态扩容的 Object 数组实现,不是链式结构,也不是红黑树。 它不保证线程安全,也不支持 null 元素,插入和删除操作的时间复杂度都是 O(log n)。
数组如何模拟二叉堆结构
Java 的 PriorityQueue 内部使用一个 Object[] queue 数组存储元素,索引从 0 开始。它通过数学关系隐式维护完全二叉树结构:
- 若节点索引为 i,其左子节点索引是 2*i + 1
- 右子节点索引是 2*i + 2
- 父节点索引是 (i - 1) / 2(整数除法)
这种映射让数组既能紧凑存储,又能快速定位父子关系,无需额外指针。
插入(offer)时的上浮(siftUp)过程
新元素添加到数组末尾,然后不断与父节点比较,若比父小(最小堆),就交换位置,直到满足堆序性:
- 先检查是否需要扩容(
queue.length == size时触发 grow) - 把新元素放在
queue[size],然后调用siftUp(int k, E x) - 循环中计算 parent = (k - 1) >>> 1,若
x比queue[parent]小,就上移 - 注意:这里用的是无符号右移
>>>,等价于 (k-1)/2,但对负数更安全(实际 k ≥ 0,本质一样)
删除队首(poll)时的下沉(siftDown)过程
取出索引 0 的元素后,把最后一个元素移到堆顶,再逐层与较小的子节点比较并下沉:
- 取走
queue[0],将queue[size-1]赋给queue[0],size 减 1 - 调用
siftDown(int k, E x),从根开始向下调整 - 每次找左右子节点中较小者(若存在),若
x大于该子节点,就交换,继续下沉 - 终止条件是:k 超出有效范围,或
x小于等于两个子节点(满足堆性质)
Comparator 和自然排序的支持机制
PriorityQueue 支持两种排序方式,统一由内部的 comparator 字段控制:
- 构造时传入 Comparator → 使用该比较器;否则要求元素实现 Comparable
- 所有比较操作都委托给
comparator.compare(a, b)或a.compareTo(b) - 堆调整过程中,所有大小判断(如
compare(x, queue[parent]) )都基于此,不硬编码逻辑
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











