引言
继上篇文章讲过了Java中的List之后,接下来我们会关注另外一种集合类型——Queue。
Queue,也就是队列,一种先进先出的数据结构。在Java中,从是否可以从尾部获取元素分成了普通队列以及双端队列。从是否会阻塞区分则分成了阻塞队列和非阻塞队列。这篇文章会从两个方面对队列进行介绍,第一部分主要介绍队列的特点,第二部分会针对Java中一些比较典型的实现进行具体分析。
有一个小细节需要注意的就是,目前队列里面一般是不允许添加null元素的。
队列简介
首先还是看一下队列的类图。
从类图中我们能够看到,一共有4个接口类,Queue
,BlockingQueue
,TransferQueue
以及Deque
。这四个类分别定了四种类型的队列的基本行为。首先我们会针对比较常用的Queue
以及BlockingQueue
来展开叙述。
Queue
Queue
是所有队列都必须实现的接口,在这个接口里面,定义了队列最基本的方法。
public interface Queue<E> extends Collection<E> {
boolean add(E e); //添加元素,元素不可为null,若添加失败,则抛出异常
boolean offer(E e); //添加元素,元素不可为null,添加失败,返回false,不抛出异常
E remove(); //移除队列首部元素,若队列为空,则抛出异常
E poll(); //移除队列首部,若队列为空,则返回null
E element();//获取队列首部元素,若队列为空,则抛出异常
E peek();//获取队列首部元素,若队列为空,则返回null
}
简单来看,队列里的接口主要定义了三个方法,添加元素,获取元素,删除元素,而又针对每个方法都定义了两种版本的(一种操作失败则返回异常,另外一种操作失败则返回null或者是false)。
BlockingQueue
BlockingQueue
则定义了一些会发生等待的场景。如在队列为空的时候进行元素获取或者是在队列已经满了的时候进行元素添加。
public interface BlockingQueue<E> extends Queue<E> {
boolean add(E e); //将元素添加到队列尾端,若添加失败,直接抛出异常
boolean offer(E e);//将元素添加到队列尾端,若添加失败,直接返回false
void put(E e) throws InterruptedException; //将元素添加到队列尾端,若队列已满则将线程挂起等待
boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException; //将元素添加到队列尾端,若队列已满,则等待一段时间,若超时后仍无空间,直接返回false
E take() throws InterruptedException;//获取队列首个元素,若队列为空,则将线程挂起进行等待
E poll(long timeout, TimeUnit unit)
throws InterruptedException; //获取队列首个元素,若队列为空,则等待一段时间,若超时后仍无空间,返回null
int remainingCapacity();//获取队列的剩余空间
boolean remove(Object o);//通过equal判断元素是否存在队列中,若存在,则将其移除
public boolean contains(Object o);//通过equal判断元素是否存在队列中,若存在,返回true
int drainTo(Collection<? super E> c);//将队列中所有元素转移到一个新的集合中,返回值为转移成功的元素数量
int drainTo(Collection<? super E> c, int maxElements);//将队列中所有元素转移到一个新的集合中,最多转移maxElements个,返回值为转移成功的元素数量
}
从方法定义上来看,由于BlockingQueue
要确保在高并发下的线程安全,因此它提供了更多的方法进行获取和删除队列元素。
具体实现
接下来还是针对具体的实现来研究具体的队列。
PriorityQueue
PriorityQueue
是一个优先队列。优先队列的意思就是,从队列里面获取元素的时候,会根据其优先级,从小到大进行获取,而非元素的添加顺序。这要求我们在使用优先队列的时候,要么使用实现了Comparable
的类进行元素添加,要么在初始化队列的时候指定Comparator
。
PriorityQueue
是基于堆排序算法来实现其优先顺序的。
首先我们来看下其内部成员变量
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; //默认容量
transient Object[] queue; // 使用数组对元素进行存储
private int size = 0; //初始化的队列大小,为0
private final Comparator<? super E> comparator; //自定义的比较器
transient int modCount = 0; //版本号
}