大家都知道队列都遵循(First-In-First-Out)先进先出的规则,但是在特定场景下想改变取出元素的方式就可以使用到优先队列PriorityBlockingQueue。
比如:银行VIP、机场VIP优先等。
PriorityQueue
PriorityQueue
类在Java1.5
中引入的,它是Java集合框架的一部分。PriorityQueue是基于优先堆的一个无界队列
,它是一个Queue
默认情况下它 根据自然排序,当然我们也可以定制比较器,自行自定义排序,从而实现自己的优先级逻辑。
public class PriorityQueue<E> extends AbstractQueue<E>
implements java.io.Serializable {
private static final long serialVersionUID = -7720805057305804111L;
private static final int DEFAULT_INITIAL_CAPACITY = 11;
/**
* Priority queue represented as a balanced binary heap: the two
* children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The
* priority queue is ordered by comparator, or by the elements'
* natural ordering, if comparator is null: For each node n in the
* heap and each descendant d of n, n <= d. The element with the
* lowest value is in queue[0], assuming the queue is nonempty.
*/
transient Object[] queue; // non-private to simplify nested class access
/**
* The number of elements in the priority queue.
*/
private int size = 0;
/**
* The comparator, or null if priority queue uses elements'
* natural ordering.
*/
private final Comparator<? super E> comparator;
/**
* The number of times this priority queue has been
* <i>structurally modified</i>. See AbstractList for gory details.
*/
transient int modCount = 0; // non-private to simplify nested class access
/**
* Creates a {@code PriorityQueue} with the default initial
* capacity (11) that orders its elements according to their
* {@linkplain Comparable natural ordering}.
*/
public PriorityQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
/**
* Creates a {@code PriorityQueue} with the specified initial
* capacity that orders its elements according to their
* {@linkplain Comparable natural ordering}.
*
* @param initialCapacity the initial capacity for this priority queue
* @throws IllegalArgumentException if {@code initialCapacity} is less
* than 1
*/
public PriorityQueue(int initialCapacity) {
this(initialCapacity, null);
}
/**
* Creates a {@code PriorityQueue} with the default initial capacity and
* whose elements are ordered according to the specified comparator.
*
* @param comparator the comparator that will be used to order this
* priority queue. If {@code null}, the {@linkplain Comparable
* natural ordering} of the elements will be used.
* @since 1.8
*/
public PriorityQueue(Comparator<? super E> comparator) {
this(DEFAULT_INITIAL_CAPACITY, comparator);
}
/**
* Creates a {@code PriorityQueue} with the specified initial capacity
* that orders its elements according to the specified comparator.
*
* @param initialCapacity the initial capacity for this priority queue
* @param comparator the comparator that will be used to order this
* priority queue. If {@code null}, the {@linkplain Comparable
* natural ordering} of the elements will be used.
* @throws IllegalArgumentException if {@code initialCapacity} is
* less than 1
*/
public PriorityQueue(int initialCapacity,
Comparator<? super E> comparator) {
// Note: This restriction of at least one is not actually needed,
// but continues for 1.5 compatibility
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.queue = new Object[initialCapacity];
this.comparator = comparator;
}
/**
* Creates a {@code PriorityQueue} containing the elements in the
* specified collection. If the specified collection is an instance of
* a {@link SortedSet} or is another {@code PriorityQueue}, this
* priority queue will be ordered according to the same ordering.
* Otherwise, this priority queue will be ordered according to the
* {@linkplain Comparable natural ordering} of its elements.
*
* @param c the collection whose elements are to be placed
* into this priority queue
* @throws ClassCastException if elements of the specified collection
* cannot be compared to one another according to the priority
* queue's ordering
* @throws NullPointerException if the specified collection or any
* of its elements are null
*/
@SuppressWarnings("unchecked")
public PriorityQueue(Collection<? extends E> c) {
if (c instanceof SortedSet<?>) {
SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
this.comparator = (Comparator<? super E>) ss.comparator();
initElementsFromCollection(ss);
}
else if (c instanceof PriorityQueue<?>) {
PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
this.comparator = (Comparator<? super E>) pq.comparator();
initFromPriorityQueue(pq);
}
else {
this.comparator = null;
initFromCollection(c);
}
}
...
public long estimateSize() {
return (long) (getFence() - index);
}
public int characteristics() {
return Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.NONNULL;
}
}
}
Demo:
输出:
上面没有指定比较器,所以就按照自然排序的规则排了。
下面我们自己指定一个比较器试试:
Demo:
输出:
优先队列不允许空值,而且不支持non-comparable(不可比较)的对象,比如用户自定义的类。 注意:此处需要注意的是,你是基于某个字段做优先级排序,只需要那个字段可比较即可,而不需要整个类都实现比较器接口
优先队列的头是基于自然排序或者Comparator排序的最小元素。如果有多个对象拥有同样的排序,那么就可能随机地取其中任意一个
。当我们获取队列时,返回队列的头对象。
PriorityBlockingQueue
1、add(E e) : 将指定元素插入此优先级队列。
2、clear() :完全移除此队列中的所有元素。
3、contains(Object o) :如果队列包含指定的元素,则返回 true。
4、iterator() :返回在此队列元素上进行迭代的迭代器,返回值为Iterator。
5、offer(E e) :将指定元素插入此优先级队列,返回值为Boolean。
6、offer(E e, long timeout, TimeUnit unit) : 将指定元素插入此优先级队列,返回值为Boolean。
7、peek() :获取但不移除此队列的头;如果此队列为空,则返回 null。
8、poll() :获取并移除此队列的头,如果此队列为空,则返回 null。
9、poll(long timeout, TimeUnit unit) :获取并移除此队列的头部,在指定的等待时间前等待可用的元素(如果有必要)。
10、put(E e) :将指定元素插入此优先级队列。
11、remove(Object o) :从队列中移除指定元素的单个实例(如果存在),返回值为Boolean。
12、size() :返回此 collection 中的元素数。
13、take() :获取并移除此队列的头部,在元素变得可用之前一直等待(如果有必要)。
15、Object[] toArray() :返回包含此队列所有元素的数组。
16、toString() :返回此 collection 的字符串表示形式,返回值为String。
它的构造函数和PriorityQueue
基本一样,因此使用方式其实也是差不多的。只是它增加了对多线程的处理、以及对阻塞队列特性的支持~~~~
Demo:
输出:
看输出结果和上面一模一样。
总结
(阻塞)队列能解决我们最常规的排队的问题,而优先级队这种数据结构能够解决我们业务中可能会用到的VIP排队问题。
比如有个常规的使用场景:优先级消息(MQ消息),有的就是基于JDK的优先级队列来实现的~~~