专栏首页编码前线Java优先队列(PriorityQueue)示例

Java优先队列(PriorityQueue)示例

我们知道队列是遵循先进先出(First-In-First-Out)模式的,但有些时候需要在队列中基于优先级处理对象。举个例子,比方说我们有一个每日交易时段生成股票报告的应用程序,需要处理大量数据并且花费很多处理时间。客户向这个应用程序发送请求时,实际上就进入了队列。我们需要首先处理优先客户再处理普通用户。在这种情况下,Java的PriorityQueue(优先队列)会很有帮助。

PriorityQueue类在Java1.5中引入并作为 Java Collections Framework 的一部分。PriorityQueue是基于优先堆的一个无界队列,这个优先队列中的元素可以默认自然排序或者通过提供的Comparator(比较器)在队列实例化的时排序。

优先队列不允许空值,而且不支持non-comparable(不可比较)的对象,比如用户自定义的类。优先队列要求使用Java Comparable和Comparator接口给对象排序,并且在排序时会按照优先级处理其中的元素。

优先队列的头是基于自然排序或者Comparator排序的最小元素。如果有多个对象拥有同样的排序,那么就可能随机地取其中任意一个。当我们获取队列时,返回队列的头对象。

优先队列的大小是不受限制的,但在创建时可以指定初始大小。当我们向优先队列增加元素的时候,队列大小会自动增加。

PriorityQueue是非线程安全的,所以Java提供了PriorityBlockingQueue(实现BlockingQueue接口)用于Java多线程环境。

我们有一个用户类Customer,它没有提供任何类型的排序。当我们用它建立优先队列时,应该为其提供一个比较器对象。

Customer.java

package com.journaldev.collections;
 
public class Customer {
 
    private int id;
    private String name;
 
    public Customer(int i, String n){
        this.id=i;
        this.name=n;
    }
 
    public int getId() {
        return id;
    }
 
    public String getName() {
        return name;
    }
 
}

我们使用Java随机数生成随机用户对象。对于自然排序,我们使用Integer对象,这也是一个封装过的Java对象。

下面是最终的测试代码,展示如何使用PriorityQueue:

PriorityQueueExample.java

package com.journaldev.collections;
 
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
 
public class PriorityQueueExample {
 
    public static void main(String[] args) {
 
        //优先队列自然排序示例
        Queue<Integer> integerPriorityQueue = new PriorityQueue<>(7);
        Random rand = new Random();
        for(int i=0;i<7;i++){
            integerPriorityQueue.add(new Integer(rand.nextInt(100)));
        }
        for(int i=0;i<7;i++){
            Integer in = integerPriorityQueue.poll();
            System.out.println("Processing Integer:"+in);
        }
 
        //优先队列使用示例
        Queue<Customer> customerPriorityQueue = new PriorityQueue<>(7, idComparator);
        addDataToQueue(customerPriorityQueue);
 
        pollDataFromQueue(customerPriorityQueue);
 
    }
 
    //匿名Comparator实现
    public static Comparator<Customer> idComparator = new Comparator<Customer>(){
 
        @Override
        public int compare(Customer c1, Customer c2) {
            return (int) (c1.getId() - c2.getId());
        }
    };
 
    //用于往队列增加数据的通用方法
    private static void addDataToQueue(Queue<Customer> customerPriorityQueue) {
        Random rand = new Random();
        for(int i=0; i<7; i++){
            int id = rand.nextInt(100);
            customerPriorityQueue.add(new Customer(id, "Pankaj "+id));
        }
    }
 
    //用于从队列取数据的通用方法
    private static void pollDataFromQueue(Queue<Customer> customerPriorityQueue) {
        while(true){
            Customer cust = customerPriorityQueue.poll();
            if(cust == null) break;
            System.out.println("Processing Customer with ID="+cust.getId());
        }
    }
 
}

注意我用实现了Comparator接口的Java匿名类,并且实现了基于id的比较器。

当我运行以上测试程序时,我得到以下输出:

Processing Integer:9
Processing Integer:16
Processing Integer:18
Processing Integer:25
Processing Integer:33
Processing Integer:75
Processing Integer:77
Processing Customer with ID=6
Processing Customer with ID=20
Processing Customer with ID=24
Processing Customer with ID=28
Processing Customer with ID=29
Processing Customer with ID=82
Processing Customer with ID=96

从输出结果可以清楚的看到,最小的元素在队列的头部因而最先被取出。如果不实现Comparator,在建立customerPriorityQueue时会抛出ClassCastException。

Exception in thread "main" java.lang.ClassCastException: com.journaldev.collections.Customer cannot be cast to java.lang.Comparable
    at java.util.PriorityQueue.siftUpComparable(PriorityQueue.java:633)
    at java.util.PriorityQueue.siftUp(PriorityQueue.java:629)
    at java.util.PriorityQueue.offer(PriorityQueue.java:329)
    at java.util.PriorityQueue.add(PriorityQueue.java:306)
    at com.journaldev.collections.PriorityQueueExample.addDataToQueue(PriorityQueueExample.java:45)
    at com.journaldev.collections.PriorityQueueExample.main(PriorityQueueExample.java:25)

本文分享自微信公众号 - 编码前线(gh_acef1225aadd)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-08-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JAVA面试50讲之6:HashMap常见问题

    并发项目中偶尔会遇到HashMap死循环造成CPU100%,重启后问题消失,隔一段时间又会反复出现。今天在这里来仔细剖析下多线程情况下HashMap所带来的问题...

    用户1205080
  • 布隆过滤器(Bloom Filter)详解

    直观的说,bloom算法类似一个hash set,用来判断某个元素(key)是否在某个集合中。 和一般的hash set不同的是,这个算法无需存储key的值,对...

    用户1205080
  • Flink 1.7.0 安装、配置与使用

    Apache Flink是一个面向分布式数据流处理和批量数据处理的开源计算平台,它能够基于同一个Flink运行时,提供支持流处理和批处理两种类型应用的功能。

    用户1205080
  • 玩转jupyter

    Jupyter Notebook是一个开源的Web应用程序,可以让您创建和实时共享代码、方程式、可视化和说明文本等文档。主要用于:数据清理与转换,数值模拟,统计...

    尾尾部落
  • Qemu-KVM 网络性能优化实践

    在做优化之前,腾讯云上使用的母机单队列,性能只有14w pps,已有的多队列版本,在20w+ pps左右,不是很理想......

    serena
  • GlobeImposter3.0 勒索分析

    tip:如何在app.any.run下载木马 首先访问https://app.any.run/,然后点击右下角的trojan

    网e渗透安全部
  • Salesforce队列(Queue)应用场景介绍

    Salesforce队列(Queue)帮助你的团队管理销售线索,个案,服务合同以及其它的自定义对象。当你将一条记录手动放入到队列中或者通过个案和线索的自动分配规...

    臭豆腐
  • Java数据结构和算法(五)——队列

      前面一篇博客我们讲解了并不像数组一样完全作为存储数据功能,而是作为构思算法的辅助工具的数据结构——栈,本篇博客我们介绍另外一个这样的工具——队列。栈是后进先...

    IT可乐
  • 13张PPT带你了解主动式消息队列处理集群

    偷偷和你们说,我搞了一份内部资料,该内部资料共有13张PPT,据作者透露,该PPT至少花了整整1周时间才编写完成,其内容简洁明了,内容深度足够,易于初学者理解,...

    梁规晓
  • Mac OS X下GnuPlot的安装

    Gnuplot是一个科学界广泛使用的作图软件,从Unix软件发展而来,是一款免费软件。因为其强大的作图功能,逐渐也有其他行业的人来维护支持这个软件,使其变的越来...

    大江小浪

扫码关注云+社区

领取腾讯云代金券