【小家Java】Java优先队列PriorityQueue、PriorityBlockingQueue使用示例

简介: 【小家Java】Java优先队列PriorityQueue、PriorityBlockingQueue使用示例

前言


我们知道队列是遵循先进先出(First-In-First-Out)模式的,但有些时候需要在队列中基于优先级处理对象。


为什么优先级队列,其实很好理解。比如银行的VIP客户、各大机场的VIP客户的优先登机等,都是优先级队列的体现。而正常排队的都属于普通队列~


PriorityQueue


PriorityQueue类在Java1.5中引入的,它是Java集合框架的一部分。PriorityQueue是基于优先堆的一个无界队列,它是一个Queue


默认情况下它 根据自然排序,当然我们也可以定制比较器,自行自定义排序,从而实现自己的优先级逻辑。


// @since 1.5
public class PriorityQueue<E> extends AbstractQueue<E> implements java.io.Serializable {
  // 构造函数
    public PriorityQueue() {
        this(DEFAULT_INITIAL_CAPACITY, null);
    }
    public PriorityQueue(int initialCapacity) {
        this(initialCapacity, null);
    }
    //@since 1.8
    public PriorityQueue(Comparator<? super E> comparator) {
        this(DEFAULT_INITIAL_CAPACITY, comparator);
    }
    // 自己指定初始化因子,指定比较器
    public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) {
      // initialCapacity  不能小于1
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.queue = new Object[initialCapacity];
        this.comparator = comparator;
    }
    // 
  public PriorityQueue(Collection<? extends E> c) {...}
  public PriorityQueue(SortedSet<? extends E> c) {...}
  ...
}
// @since 1.5  AbstractQueue这个类也是1.5后出现的  我们发现它还继承自AbstractCollection  所以它也是个Collection
public abstract class AbstractQueue<E> extends AbstractCollection<E> implements Queue<E> {
  ...
}


Demo Show:


    public static void main(String[] args) {
        PriorityQueue<String> priorityQueue = new PriorityQueue<>();
        priorityQueue.add("orange");
        priorityQueue.add("fig");
        priorityQueue.add("watermelon");
        priorityQueue.add("lemon");
        while (priorityQueue.size() != 0) {
            System.out.println(priorityQueue.remove());
        }
    }


输出:

fig
lemon
orange
watermelon


没有指定比较器,所以就按照自然排序的规则排了。下面我们自己指定一个比较器试试:


// 指定一个倒序输出的比较器
PriorityQueue<String> priorityQueue = new PriorityQueue<>(Comparator.reverseOrder());


输出:

fig
lemon
orange
watermelon


因此我们看到优先级队列的使用,使用起来还是非常的简单的。


优先队列不允许空值,而且不支持non-comparable(不可比较)的对象,比如用户自定义的类。

注意:此处需要注意的是,你是基于某个字段做优先级排序,只需要那个字段可比较即可,而不需要整个类都实现比较器接口


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


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


PriorityBlockingQueue


在之前有篇博文:

【小家java】BlockingQueue阻塞队列详解以及5大实现(ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue…)


本文重点不介绍它阻塞的特性,而是介绍它优先级队列的使用办法。


它是一个无界有序的阻塞队列,排序规则和之前介绍的PriorityQueue一致,只是增加了阻塞操作。同样的该队列不支持插入null元素,同时不支持插入非comparable的对象。


该类不保证同等优先级的元素顺序,如果你想要强制顺序,就需要考虑自定义顺序或者是Comparator使用第二个比较属性


public class PriorityBlockingQueue<E> extends AbstractQueue<E>
    implements BlockingQueue<E>, java.io.Serializable {
    public PriorityBlockingQueue() {
        this(DEFAULT_INITIAL_CAPACITY, null);
    }
   public PriorityBlockingQueue(int initialCapacity) {
        this(initialCapacity, null);
    }
    public PriorityBlockingQueue(int initialCapacity, Comparator<? super E> comparator) {
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        this.comparator = comparator;
        this.queue = new Object[initialCapacity];
    }
  public PriorityBlockingQueue(Collection<? extends E> c) {...}
    ...
}


它的构造函数和PriorityQueue基本一样,因此使用方式其实也是差不多的。只是它增加了对多线程的处理、以及对阻塞队列特性的支持~~~~


Demo Show:

    public static void main(String[] args) {
        // 注意的是:它没有提供和PriorityQueue一样的只提供比较器的构造函数,我个人觉得是JDK忘了~~~~
        PriorityBlockingQueue<String> priorityQueue = new PriorityBlockingQueue<>(11,Comparator.reverseOrder());
        priorityQueue.add("orange");
        priorityQueue.add("fig");
        priorityQueue.add("watermelon");
        priorityQueue.add("lemon");
        while (priorityQueue.size() != 0) {
            System.out.println(priorityQueue.remove());
        }
    }


输出:


watermelon
orange
lemon
fig


可以看出,使用方式几乎一样~~~


总结


(阻塞)队列能解决我们最常规的排队的问题,而优先级队这种数据结构能够解决我们业务中可能会用到的VIP排队问题。

比如有个常规的使用场景:优先级消息(MQ消息),有的就是基于JDK的优先级队列来实现的~~~


相关文章
|
2月前
|
存储 Java API
【Azure 存储服务】Java Storage SDK 调用 uploadWithResponse 代码示例(询问ChatGTP得代码原型后人力验证)
【Azure 存储服务】Java Storage SDK 调用 uploadWithResponse 代码示例(询问ChatGTP得代码原型后人力验证)
|
7天前
|
JavaScript 前端开发 Java
Java 8 新特性详解及应用示例
Java 8 新特性详解及应用示例
|
2月前
|
消息中间件 负载均衡 Java
"深入Kafka核心:探索高效灵活的Consumer机制,以Java示例展示数据流的优雅消费之道"
【8月更文挑战第10天】在大数据领域,Apache Kafka凭借其出色的性能成为消息传递与流处理的首选工具。Kafka Consumer作为关键组件,负责优雅地从集群中提取并处理数据。它支持消息的负载均衡与容错,通过Consumer Group实现消息的水平扩展。下面通过一个Java示例展示如何启动Consumer并消费数据,同时体现了Kafka Consumer设计的灵活性与高效性,使其成为复杂消费场景的理想选择。
97 4
|
2月前
|
JSON Java API
【Azure API 管理】通过Java APIM SDK创建一个新的API,如何为Reqeust的Representation设置一个内容示例(Sample)?
【Azure API 管理】通过Java APIM SDK创建一个新的API,如何为Reqeust的Representation设置一个内容示例(Sample)?
|
2月前
|
存储 缓存 Java
|
2月前
|
设计模式 存储 Java
掌握Java设计模式的23种武器(全):深入解析与实战示例
掌握Java设计模式的23种武器(全):深入解析与实战示例
|
2月前
|
存储 缓存 监控
Java本地高性能缓存实践问题之在EncacheTest示例中正确移除一个缓存实例的问题如何解决
Java本地高性能缓存实践问题之在EncacheTest示例中正确移除一个缓存实例的问题如何解决
|
4月前
|
Java
static关键字在Java中的应用场景与示例
static关键字在Java中的应用场景与示例
|
4月前
|
Java Android开发
Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。
【6月更文挑战第23天】 Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。客户端连接服务器,发送&quot;Hello, Server!&quot;后关闭。注意Android中需避免主线程进行网络操作。
74 4
|
4月前
|
Java
java代码示例和常用代码解读
java代码示例和常用代码解读
48 1
下一篇
无影云桌面