文章目录
问题发现
代码如下:
java
public class Main {
public static void main(String[] args) {
PriorityQueue<Double> pq = new PriorityQueue<>();
pq.add(3.6);
pq.add(1.2);
pq.add(5.9);
pq.add(2.4);
pq.forEach(System.out::println);
}
}
输出结果:
1.2
2.4
5.9
3.6
可以看到输出的顺序既不是添加顺序也不是按照元素大小顺序输出
原因
PriorityQueue
使用 forEach
方法输出元素乱序的原因与其内部实现有关。forEach
方法是对集合进行迭代操作,它并不保证按照特定的顺序遍历元素。在 PriorityQueue
的实现中,元素的顺序是根据堆结构决定的,而不是插入的顺序或者元素自身的顺序。
PriorityQueue
是使用堆实现的,堆是一种完全二叉树的数据结构,它具有以下特性:
- 对于最小堆,父节点的值小于等于子节点的值。
- 对于最大堆,父节点的值大于等于子节点的值。
当你向 PriorityQueue
中添加元素时,它会根据优先级规则(最小堆或最大堆)进行调整,以保持堆的特性。因此,堆中的元素的顺序并不是按照插入的顺序或者元素自身的顺序。
而使用 PriorityQueue
的 forEach
方法对堆进行迭代时,它会按照内部的二叉树结构进行遍历,而不是按照元素的实际顺序。这就导致了在使用 forEach
方法输出元素时,它们的顺序是乱序的。
如果希望按照特定顺序遍历 PriorityQueue
中的元素,你可以使用其他方式,如循环遍历或使用迭代器来逐个取出元素。
正确输出方式
正序输出
代码如下:
java
public class Main {
public static void main(String[] args) {
PriorityQueue<Double> pq = new PriorityQueue<>();
pq.add(3.6);
pq.add(1.2);
pq.add(5.9);
pq.add(2.4);
// pq.forEach(System.out::println);
while (!pq.isEmpty()){
System.out.println(pq.poll());
}
}
}
输出结果:
1.2
2.4
3.6
5.9
可以发现输出的顺序是按照元素大小正序输出的
倒序输出
方法一:自定义比较器
你可以创建一个自定义的比较器类,然后在创建 PriorityQueue
对象时将该比较器作为参数传入。比较器将比较两个元素的值,并根据需要对它们的顺序进行调整。
示例代码:
java
import java.util.Comparator;
import java.util.PriorityQueue;
public class Main {
public static void main(String[] args) {
// 创建自定义的比较器
Comparator<Double> reverseComparator = new Comparator<Double>() {
public int compare(Double d1, Double d2) {
return Double.compare(d2, d1); // 逆序比较
}
};
// 创建带有自定义比较器的 PriorityQueue
PriorityQueue<Double> pq = new PriorityQueue<>(reverseComparator);
// 添加元素
pq.add(3.6);
pq.add(1.2);
pq.add(5.9);
pq.add(2.4);
// 输出元素(按逆序顺序)
while (!pq.isEmpty()) {
System.out.println(pq.poll());
}
}
}
输出结果:
5.9
3.6
2.4
1.2
方法二:使用负数
另一种简单的方法是,将要存储的 Double
值取其负数,然后正常地使用 PriorityQueue
。这样一来,元素将以逆序的方式进行排序。
示例代码:
java
import java.util.PriorityQueue;
public class Main {
public static void main(String[] args) {
// 创建 PriorityQueue
PriorityQueue<Double> pq = new PriorityQueue<>();
// 添加元素(取负数)
pq.add(-3.6);
pq.add(-1.2);
pq.add(-5.9);
pq.add(-2.4);
// 输出元素(按逆序顺序,注意取负数后要再次取负数)
while (!pq.isEmpty()) {
System.out.println(-pq.poll());
}
}
}
输出结果:
5.9
3.6
2.4
1.2