PriorityQueue底层使用Object[]数组实现的一个最小二叉堆,来到达一个优先队列功能,是线程不安全的。它与FIFO的队列的区别在于,优先队列每次出队的元素都是优先级最高的元素。那么怎么确定哪一个元素的优先级最高呢?PriorityQueue使用二叉堆这种数据结构,用户可以自定义的Comparator来确定每次出队的元素总是队列里面最小的,而元素的大小比较方法可以由用户指定Comparator(Comparator就相当于指定优先级),接下来我们先来看看堆这种数据结构。
1.二叉堆介绍
堆数据结构的特性
-
堆中某个节点的值总是不大于或不小于其父节点的值。
-
堆总是一棵完全二叉树。
在堆数据结构又有很多种,而PriorityQueue使用的便是二叉堆,二叉堆是一种特殊的堆,二叉堆是一颗完全二叉树或者是近似一颗完全二叉树。
(1)二叉堆分类
二叉堆分为两种:最大堆和最小堆。PriorityQueue使用的便是最小二叉堆,根的位置元素永远是最小的。
-
最大堆:父结点的键值总是大于或等于任何一个子节点的键值。
-
最小堆:父结点的键值总是小于或等于任何一个子节点的键值。
(2)二叉堆结构
这里我们最小二叉堆为例,将一个二叉堆结构用一颗完全二叉树表示出来,各个元素位置如下图 :

上图就是一颗完全二叉树(二叉堆),二叉堆特点:那就是在第n层深度被填满之前,不会开始填第n+1层深度,且元素插入是从左往右填满。基于这个特点我们用数据结构来表示一个二叉堆,如下图:

PriorityQueue内部实现就是使用一个Object[]数组来表示二叉堆的,基于数组实现的二叉堆结构具有以下特点:
-
跟节点:数组实现的二叉堆,根节点在index=0位置上。
-
左孩子:数组n位置上的元素,其左孩子在[2n+1]位置上。
-
右孩子:数组n位置上的元素,其右孩子在 2(n+1) 位置上。
-
父节点:数组n位置上的元素,其父节点在 (n-1)/2 位置上。
到此二叉堆的结构就了解完了,接下来在继续看看PriorityQueue是怎么实现的?
2.PriorityQueue源码分析
(1)PriorityQueue主要结构
PriorityQueue继承了AbstractQueue抽象类,并实现了Serializable接口,AbstractQueue抽象类实现了Queue接口,对元素添加、删除等方法进行了一些通用的定义。PriorityQueue的底层存储结构相关定义如下:
public class PriorityQueue<E> extends AbstractQueue<E>
implements java.io.Serializable {
private static final long serialVersionUID = -7720805057305804111L;
// 用数组实现的二叉堆: 如前面的说法一样,左右子节点位置、父节点位置、根节点位置。
/**
* 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
//数组默认初始化大小
private static final int DEFAULT_INITIAL_CAPACITY = 11;
//队列的元素数量
private int size = 0;
//自定义比较器
private final Comparator<? super E> comparator;
//队列修改次数:修改版本
transient int modCount = 0;
//queue数组的最大长度,即队列的最大长度
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
}
可以看到PriorityQueue也是基于数组来实现一个二叉堆,PriorityQueue是一个有限队列,数据queue最大不能超过Integer.MAX_VALUE - 8,PriorityQueue中的优先级可以由用户指定,就是用户指定元素的Comparator比较器。

最低0.47元/天 解锁文章
1601

被折叠的 条评论
为什么被折叠?



