java中priorityqueue通过维护大小为k的最小堆实现top k,新元素仅在大于堆顶时入堆并淘汰堆顶,时间复杂度o(log k),空间复杂度o(k)。

Java 中 PriorityQueue 可以高效实现动态流数据中的 Top K(最大 K 个元素),核心思路是:**维护一个大小为 K 的最小堆,堆顶始终是当前 Top K 中的最小值,新元素只在比堆顶大时才入堆并淘汰堆顶**。
用最小堆维护 Top K 大元素
PriorityQueue 默认是最小堆(升序),适合求 Top K 大 —— 因为我们要快速淘汰“不够大”的元素。只要队列 size 小于 K,直接 add;达到 K 后,只保留更大的数:
- 新元素 ≤ 堆顶 → 跳过(它进不了 Top K)
- 新元素 > 堆顶 → poll 堆顶 + offer 新元素(替掉当前 Top K 中最小的那个)
代码写法简洁可靠
无需手动排序或遍历,每次插入/更新时间复杂度仅 O(log K),空间固定 O(K):
PriorityQueue<integer> topK = new PriorityQueue(); // 最小堆
int k = 3;
for (int num : streamData) {
if (topK.size() topK.peek()) {
topK.poll();
topK.offer(num);
}
}
// 最终 topK 里就是最大的 3 个数(顺序不定)
</integer>
注意边界与类型适配
实际使用需留意几点:
- 流为空或 K ≤ 0 时提前处理,避免异常
- 若元素类型不是基本类型(如自定义对象),需提供
Comparator或让类实现Comparable,确保按目标字段(如 score)比较 - 需要按降序输出结果时,可把堆中元素转成 List 后
Collections.sort(list, Collections.reverseOrder()),但不要在堆内做 reverse
和 TreeSet / 排序数组对比
相比其他方式:
- TreeSet 自动去重且有序,但无法直接控制容量,重复元素会丢失,且删除最小元素不如堆明确
- 每次全排序 时间 O(N log N),流式场景完全不可行
- PriorityQueue 恰好平衡了效率、内存和逻辑清晰度,是标准解法
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











