Java Priority Queue(PriorityQueue)示例
欢迎使用Java教程中的Priority Queue。
我们知道"队列"遵循先进先出模型,但是有时我们需要根据优先级来处理队列中的对象。
那就是使用JavaPriorityQueue
的时候。
例如,假设我们有一个应用程序可以为每日交易生成股票报告。
该应用程序处理大量数据,并花费时间来处理它。
因此,客户正在将请求发送到实际上正在排队的应用程序,但是我们要先处理高级客户,然后再处理标准客户。
因此,在这种情况下,用Java实现PriorityQueue确实很有帮助。
Java优先级队列
" PriorityQueue"类是Java 1.5中引入的,它是Java Collections Framework的一部分。
PriorityQueue是基于优先级堆的无界队列,默认情况下,优先级队列的元素以自然顺序排序。
我们可以在实例化优先级队列时提供一个用于排序的比较器。
Java Priority Queue不允许使用" null"值,因此我们无法创建不可比对象的PriorityQueue。
我们使用java Comparable和Comparator对对象进行排序,Priority Queue使用它们对元素进行优先处理。
优先级队列的头是基于自然排序或者基于比较器排序的最小元素,如果有多个具有相同排序的对象,则它可以随机轮询其中的任何一个。
当我们轮询队列时,它从队列中返回头对象。
Java Priority Queue的大小没有限制,但是我们可以在创建时指定初始容量。
当我们将元素添加到优先级队列时,其容量会自动增长。
PriorityQueue不是线程安全的,因此Java提供了PriorityBlockingQueue
类,该类实现BlockingQueue接口以在Java多线程环境中使用。
Java Priority Queue实现为入队和出队方法提供O(log(n))时间。
让我们看一下Java PriorityQueue以及Comparator的自然排序示例。
我们有一个自定义类" Customer",它不提供任何类型的排序,因此当我们尝试将其与PriorityQueue一起使用时,我们应该为此提供一个比较器对象。
Customer.java
package com.theitroad.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随机数生成来生成随机的客户对象。
对于自然排序,我将使用也是Java包装类的Integer。
这是我们的最终测试代码,显示了如何在Java中使用优先级队列。
PriorityQueueExample.java
package com.theitroad.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) { //natural ordering example of priority queue 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); } //PriorityQueue example with Comparator Queue<Customer> customerPriorityQueue = new PriorityQueue<>(7, idComparator); addDataToQueue(customerPriorityQueue); pollDataFromQueue(customerPriorityQueue); } //Comparator anonymous class implementation public static Comparator<Customer> idComparator = new Comparator<Customer>(){ @Override public int compare(Customer c1, Customer c2) { return (int) (c1.getId() - c2.getId()); } }; //utility method to add random data to Queue 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, "hyman "+id)); } } //utility method to poll data from queue 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()); } } }
注意,我正在使用java匿名类来实现Comparator接口并创建基于id的比较器。
当我在Java优先级队列示例测试程序上方运行时,它将生成以下输出。
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
从输出中可以明显看出,最少的元素在首位,并且被首先轮询。
如果我们在创建" customerPriorityQueue"时不提供比较器,则会在运行时抛出" ClassCastException"。
Exception in thread "main" java.lang.ClassCastException: com.theitroad.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.theitroad.collections.PriorityQueueExample.addDataToQueue(PriorityQueueExample.java:45) at com.theitroad.collections.PriorityQueueExample.main(PriorityQueueExample.java:25)