Java——PriorityQueue使用forEach输出元素乱序并实现逆序输出

文章目录

问题发现

代码如下:

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 是使用堆实现的,堆是一种完全二叉树的数据结构,它具有以下特性:

  1. 对于最小堆,父节点的值小于等于子节点的值。
  2. 对于最大堆,父节点的值大于等于子节点的值。

当你向 PriorityQueue 中添加元素时,它会根据优先级规则(最小堆或最大堆)进行调整,以保持堆的特性。因此,堆中的元素的顺序并不是按照插入的顺序或者元素自身的顺序。

而使用 PriorityQueueforEach 方法对堆进行迭代时,它会按照内部的二叉树结构进行遍历,而不是按照元素的实际顺序。这就导致了在使用 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
相关推荐
lang201509286 小时前
Apache Maven 项目的开发指南
java·maven·apache
rengang666 小时前
134-Spring AI Alibaba OceanBase 向量数据库示例
java·人工智能·spring·oceanbase·rag·spring ai·ai应用编程
ゞ 正在缓冲99%…6 小时前
leetcode1312.让字符串成为回文串的最少插入次数
数据结构·算法·leetcode·动态规划·记忆化搜索
靠沿7 小时前
JavaSE知识分享——继承(下)
java·开发语言
laocooon5238578867 小时前
寻找使a×b=c成立的最小进制数(2-16进制)
数据结构·算法
Catfood_Eason7 小时前
CMPP3020作业2
java·开发语言
CryptoRzz7 小时前
印度实时股票数据源接口对接文档-IPO新股、k线数据
java·开发语言·数据库·区块链
宸津-代码粉碎机7 小时前
Java内部类内存泄露深度解析:原理、场景与根治方案(附GC引用链分析)
java·开发语言·jvm·人工智能·python
東雪木7 小时前
Java基础语言进阶学习——1,JVM内存模型(堆、栈、方法区)
java·jvm·学习
毕设源码-郭学长8 小时前
【开题答辩全过程】以 常二社区线上养老院管理系统为例,包含答辩的问题和答案
java·eclipse