PriorityQueue
容器,翻一下就是优先队列
,平常一般称堆
。优先队列
的作用是将队列中的元素最小值
放到堆顶
(小顶堆
,最小的元素在顶端
,你也可以修改comparator
,使之变成大顶堆
,最大的元素在顶端
)。每当我们插入
、删除
元素,都是从堆顶
进行,优先队列
会自动重新调整堆
,将最小的元素值调整到堆顶
。
本篇博客将从源码的角度并结合相应的图解,对Java
中的PriorityQueue
容器的实现原理进行分析。为了帮助大家更好的理解PriorityQueue
,写了一篇关于堆的实现与原理分析博客,墙裂推荐各位小伙伴阅读做铺垫,链接→数据结构之堆(我猜,关于堆的这些维护细节,你肯定不清楚,不信你来看!)
注明:以下源码分析都是基于jdk 1.8.0_221
版本
Java容器之PriorityQueue源码分析目录
一、PriorityQueue
容器概述
PriorityQueue
类的申明如下:
public class PriorityQueue<E> extends AbstractQueue<E>
implements java.io.Serializable
Java
中的PriorityQueue
容器,底层是通过数组
来实现堆结构
。在前一篇博客数据结构之堆(我猜,关于堆的这些维护细节,你肯定不清楚,不信你来看!)说过,基于数组实现的堆两个重要规律:
- 下标为
index
的左、右孩子的下标分别是index * 2 + 1
、(index + 1) * 2
- 堆中有子节点的节点最大下标为
size / 2 - 1
(注意:size
为堆的大小,不是数组的大小)
二、PriorityQueue
类中的主要属性
/**
* 数组默认初始化的长度
*/
private static final int DEFAULT_INITIAL_CAPACITY = 11;
/**
* 实现堆的数组
*/
transient Object[] queue; // non-private to simplify nested class access
/**
* 优先队列中的元素数(注意需要与数组的长度区分开)
*/
private int size = 0;
/**
* 优先队列中元素比较器,通过指定comparator,可以选择构造小顶堆还是大顶堆
*/
private final Comparator<? super E> comparator;
/**
* 结构性调整(插入、删除、扩容等操作)的次数
*/
transient int modCount = 0;
三、PriorityQueue
类的构造器
/**
* 默认构造器,数组长度初始化为默认值
*/
public PriorityQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
/**
* 指定数组的初始化长度
*/
public PriorityQueue(int initialCapacity) {
this(initialCapacity, null);
}
/**
* 指定元素比较器
*/
public PriorityQueue(Comparator<? super E> comparator) {
this(DEFAULT_INITIAL_CAPACITY, comparator);
}
/**
* 数组长度、元素比较器都指定
*/
public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) {
// 数组长度不能小于1
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.queue = new Object[initialCapacity];
this.comparator = comparator;
}
/**
* 复制构造器1
* 将容器1中的元素全部放入当前创建的优先队列中
*/
@SuppressWarnings("unchecked")
public PriorityQueue(Collection<? extends E> c) {
if (c instanceof SortedSet<?>) {
// 如果容器C是SortedSet接口实现类,可初始化comparator
SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
this.comparator = (Comparator<