前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【小家Java】Java优先队列PriorityQueue、PriorityBlockingQueue使用示例

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

作者头像
YourBatman
发布2019-09-03 15:35:32
1.7K0
发布2019-09-03 15:35:32
举报
文章被收录于专栏:BAT的乌托邦BAT的乌托邦
前言

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

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

PriorityQueue

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

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

代码语言:javascript
复制
// @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:

代码语言:javascript
复制
    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());
        }
    }

输出:

代码语言:javascript
复制
fig
lemon
orange
watermelon

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

代码语言:javascript
复制
// 指定一个倒序输出的比较器
PriorityQueue<String> priorityQueue = new PriorityQueue<>(Comparator.reverseOrder());

输出:

代码语言:javascript
复制
fig
lemon
orange
watermelon

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

优先队列不允许空值,而且不支持non-comparable(不可比较)的对象,比如用户自定义的类。 注意:此处需要注意的是,你是基于某个字段做优先级排序,只需要那个字段可比较即可,而不需要整个类都实现比较器接口 优先队列的头是基于自然排序或者Comparator排序的最小元素。如果有多个对象拥有同样的排序,那么就可能随机地取其中任意一个。当我们获取队列时,返回队列的头对象。

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

PriorityBlockingQueue

在之前有篇博文:

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

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

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

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

代码语言:javascript
复制
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:

代码语言:javascript
复制
    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());
        }
    }

输出:

代码语言:javascript
复制
watermelon
orange
lemon
fig

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

总结

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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年04月26日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • PriorityQueue
  • PriorityBlockingQueue
    • 总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档