zoukankan      html  css  js  c++  java
  • java优先队列

    java优先队列

    我们知道队列是遵循先进先出(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)

  • 相关阅读:
    TSQL--按某字段列分组,在将各组中某列合并成一行
    疑难杂症--SQL SERVER 2012下数据库内存异常回收
    TSQL--删除登陆相关的用户
    杂谈--一次”失败“问题处理过程
    layer.open如何关闭自身弹出窗口
    简单的Http请求数据保存到Hdfs
    layui栅格布局问题
    redis单机版安装
    redis详细配置文件
    批量修改mysql数据库引擎
  • 原文地址:https://www.cnblogs.com/kexinxin/p/11617552.html
Copyright © 2011-2022 走看看