上一篇文章已经介绍了List的家族,今天就来看一看另一个数据类型Queue的大家族罢!
我们先看一看Queue家族的主要成员的类族结构(这里并不是所有的Queue都罗列的,不然太多了)
从图中我们可以看出,除了线性集合的统一接口Collection外,Queue家族总共有四个主要接口:Queue、Deque、BlockingQueue、BlockingDeque,四个接口相互继承,构成了Queue家族的基本体系。
此外,Queue有一个抽象实现类AbstractQueue,而Queue家族的几乎所有实现类全部继承此类,此类完成了些许统一操作,子类各自会实现不同接口以及拥有各自的独立操作。
值得一提的是,Deque的两个直接实现类并不继承这个抽象类,个人认为有两方面原因:1.语法限制,接口的继承虽然可以多元化,但是其实现类的继承只能做出单一的选择,而BlockingDeque的实现类与其去继承Deque的实现类,不如去继承BlockingQueue的;2.Deque的一个实现类LinkedList原本不属于Queue家族,只是由于其实现方式恰好可以方便于队列操作,因此才有LinkedList实现Deque的设计。关于LinkedList的实现,请转至上一篇博客jdk源码之java集合类(二)——List家族
接下来我们就根据源码一步步地讲述Queue家族成员的作用和实现。
一、接口
我们先看下Queue家族的四个接口分别干啥的。
Queue:Queue家族的基本接口,定义了一系列队列结构需要的操作:
熟悉队列这种数据结构的童鞋应该对这几个方法的定义没有太大疑问吧。队列基本包含三种操作:插入数据,获取第一个数据,获取并删除第一个数据。而这里对于这三种操作都分别定义了两种不同的操作方式,如下图:
官方的解释是这样的:在处理元素前用于保存元素的 collection。除了基本的 Collection
操作外,队列还提供其他的插入、提取和检查操作。每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(null 或 false,具体取决于操作)。插入操作的后一种形式是用于专门为有容量限制的 Queue 实现设计的;在大多数实现中,插入操作不会失败。
说的很抽象,反正只要知道,作为队列使用时,优先选择返回特殊值的那种就行了。
然后是Deque,这个数据结构代表的是双向队列,队列的进出并不只是单向的。既然数据的操作形式变成了双向的,那操作方法的定义自然也要变为原来的两倍:
这个我感觉并不需要解释。
然后是二者的Blocking。顾名思义,这两个接口定义了带有阻塞的队列。我们先来看BlockingQueue:
我们看到