我们知道队列是遵循先进先出(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,它没有提供任何类型的排序。当我们用它建立优先队列时,应该为其提供一个比较器对象。

package com.test4;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;

/**
 * @描述 :
 * @创建者 : guoxiaopeng
 * @创建时间 : 2017-7-4 上午10:03:42
 */
public class PriorityQueueExample {

    public static void main(String[] args) {
        //优先队列自然排序()
//        PriorityQueue队列默认使用ID排序
        Queue<Integer> integerPriorityQue=new PriorityQueue<>();
        Random rand=new Random();
        for (int i = 7; i > 0; i--) {
            integerPriorityQue.add(new Integer(i));
        }
        
        for (int i = 0; i < 7; i++) {
            Integer poll = integerPriorityQue.poll();
            System.out.println("processing Integer:" + poll);
        }
        
        
        //采用自定义的ID排序选择器初始化队列
        Queue<Customer> customerPriorityQueue = new PriorityQueue<>(7, idComparator);
       
        addDataToQueue(customerPriorityQueue);
 
        pollDataFromQueue(customerPriorityQueue);
        
       
    }
    //匿名Comparator实现
    public static Comparator<Customer>  idComparator=new Comparator<Customer>() {
        public int compare(Customer c1, Customer c2) {
            if(c1.getId()>c2.getId()){
                return -1;
            }
            else if(c1.getId()<c2.getId()){
                return 1;
            }
            else return 0;
        }
    };
  //用于往队列增加数据的通用方法
    private static void addDataToQueue(Queue<Customer> customerPriorityQueue){
        Random rand=new Random();
        for (int i = 0; i < 7; i++) {
            int id= rand.nextInt(1000);
            customerPriorityQueue.add(new Customer(id,"guoxiaopeng"+ id));
        }
    }
    //用于从队列取数据的通用方法
    private static void pollDataFromQueue(Queue<Customer> customerpriorityQueue){
        while(true){
            Customer ctm=customerpriorityQueue.poll();
            if(ctm==null)
                break;
            System.out.println("Processing customer with id ="+ctm.getId());
        }
    }
}

控制台输出如下:

processing Integer:1
processing Integer:2
processing Integer:3
processing Integer:4
processing Integer:5
processing Integer:6
processing Integer:7
Processing customer with id =843
Processing customer with id =804
Processing customer with id =775
Processing customer with id =613
Processing customer with id =557
Processing customer with id =492
Processing customer with id =111