java中priorityqueue默认为最小堆,可通过lambda或comparator.reverseorder()等自定义比较器灵活构建最大堆,泛型对象可基于字段排序,但比较器初始化后不可修改,需重建队列实现“切换”。
java 中的 priorityqueue 默认是最小堆,但通过自定义比较器(可用 lambda 表达式简洁实现),可以灵活切换为最大堆,无需额外封装或继承。
最小堆:使用默认构造或自然序 lambda
对于实现了 Comparable 的类型(如 Integer、String),直接使用无参构造器即可获得最小堆。若想显式表达逻辑,也可用 lambda 写出升序比较:
// 最小堆(等价于 new PriorityQueue<integer>()) PriorityQueue<integer> minHeap = new PriorityQueue((a, b) -> a - b); // 或更安全的写法(避免整数溢出) PriorityQueue<integer> minHeapSafe = new PriorityQueue(Integer::compareTo);</integer></integer></integer>
最大堆:用 lambda 实现降序比较
只需在 lambda 中交换比较顺序或取反即可。推荐使用 Comparator.reverseOrder() 或简洁 lambda:
// 最大堆:三种等效写法 PriorityQueue<integer> maxHeap1 = new PriorityQueue((a, b) -> b - a); PriorityQueue<integer> maxHeap2 = new PriorityQueue(Collections.reverseOrder()); PriorityQueue<integer> maxHeap3 = new PriorityQueue(Comparator.reverseOrder());</integer></integer></integer>
注意:用 b - a 要小心整数溢出;对 Long 等类型建议改用 Long.compare(b, a)。
泛型对象的最大/最小堆:lambda 配合属性提取
对自定义类(如 Person),可基于字段构建堆。假设 Person 有 age 字段:
record Person(String name, int age) {}
<p>// 最小堆:按 age 升序
PriorityQueue<person> minByAge = new PriorityQueue((p1, p2) -> Integer.compare(p1.age(), p2.age()));</person></p><p>// 最大堆:按 age 降序
PriorityQueue<person> maxByAge = new PriorityQueue((p1, p2) -> Integer.compare(p2.age(), p1.age()));
// 或更简洁:
PriorityQueue<person> maxByAgeV2 = new PriorityQueue(Comparator.comparingInt(Person::age).reversed());</person></person></p>运行时动态切换?不支持,但可快速重建
PriorityQueue 的比较器在初始化后不可修改。若需“切换”堆序,不能复用同一实例,但可高效重建:
- 保留原始数据(如一个
List) - 根据需要新建对应顺序的
PriorityQueue,并批量添加 - 例如:
new PriorityQueue(list, Comparator.reverseOrder())
时间复杂度仍是 O(n),比逐个 offer 更优。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











