【小家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的优先级队列来实现的~~~


相关文章
|
1月前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
65 1
|
2月前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
53 1
|
4月前
|
存储 Java API
【Azure 存储服务】Java Storage SDK 调用 uploadWithResponse 代码示例(询问ChatGTP得代码原型后人力验证)
【Azure 存储服务】Java Storage SDK 调用 uploadWithResponse 代码示例(询问ChatGTP得代码原型后人力验证)
|
1月前
|
Java
在Java中实现接口的具体代码示例
可以根据具体的需求,创建更多的类来实现这个接口,以满足不同形状的计算需求。希望这个示例对你理解在 Java 中如何实现接口有所帮助。
87 38
|
1月前
|
存储 Java 调度
Java 中的优先队列 PriorityQueue 详解
【10月更文挑战第22天】优先队列 PriorityQueue 是一种非常实用的数据结构,在许多场景中都能发挥重要作用。通过深入了解其特点和用法,我们可以更好地利用它来解决实际问题。
110 13
|
2月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
91 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
2月前
|
存储 Java
什么是带有示例的 Java 中的交错数组?
什么是带有示例的 Java 中的交错数组?
56 9
|
2月前
|
Java
让星星⭐月亮告诉你,jdk1.8 Java函数式编程示例:Lambda函数/方法引用/4种内建函数式接口(功能性-/消费型/供给型/断言型)
本示例展示了Java中函数式接口的使用,包括自定义和内置的函数式接口。通过方法引用,实现对字符串操作如转换大写、数值转换等,并演示了Function、Consumer、Supplier及Predicate四种主要内置函数式接口的应用。
32 1
|
2月前
|
Java API 网络安全
Java 发送邮件示例
本示例展示了如何使用Java编程语言发送电子邮件。通过利用JavaMail API,这段代码实现了从配置SMTP服务器,设置邮件属性,到发送邮件的全过程,为开发者提供了实用的参考。
193 10
|
3月前
|
JavaScript 前端开发 Java
Java 8 新特性详解及应用示例
Java 8 新特性详解及应用示例