有一段时间没有更新了。接着上节继续吧。java
Queue除了前面介绍的实现外,还有一种双向的Queue实现Deque。这种队列容许在队列头和尾部进行入队出队操做,所以在功能上比Queue显然要更复杂。下图描述的是Deque的完总体系图。须要说明的是LinkedList也已经加入了Deque的一部分(LinkedList是从jdk1.2 开始就存在数据结构)。数组
Deque在Queue的基础上增长了更多的操做方法。安全
从上图能够看到,Deque不只具备FIFO的Queue实现,也有FILO的实现,也就是不只能够实现队列,也能够实现一个堆栈。数据结构
同时在Deque的体系结构图中能够看到,实现一个Deque可使用数组(ArrayDeque),同时也可使用链表(LinkedList),还能够同实现一个支持阻塞的线程安全版本队列LinkedBlockingDeque。性能
对于数组实现的Deque来讲,数据结构上比较简单,只须要一个存储数据的数组以及头尾两个索引便可。因为数组是固定长度的,因此很容易就获得数组的头和尾,那么对于数组的操做只须要移动头和尾的索引便可。.net
特别说明的是ArrayDeque并非一个固定大小的队列,每次队列满了之后就将队列容量扩大一倍(doubleCapacity()),所以加入一个元素老是能成功,并且也不会抛出一个异常。也就是说ArrayDeque是一个没有容量限制的队列。线程
一样继续性能的考虑,使用System.arraycopy复制一个数组比循环设置要高效得多。对象
对于LinkedList自己而言,数据结构就更简单了,除了一个size用来记录大小外,只有head一个元素Entry。对比Map和Queue的其它数据结构能够看到这里的Entry有两个引用,是双向的队列。blog
在示意图中,LinkedList老是有一个“傀儡”节点,用来描述队列“头部”,可是并不表示头部元素,它是一个执行null的空节点。索引
队列一开始只有head一个空元素,而后从尾部加入E1(add/addLast),head和E1之间创建双向连接。而后继续从尾部加入E2,E2就在head和E1之间创建双向连接。最后从队列的头部加入E3(push/addFirst),因而E3就在E1和head之间连接双向连接。
双向链表的数据结构比较简单,操做起来也比较容易,从事从“傀儡”节点开始,“傀儡”节点的下一个元素就是队列的头部,前一个元素是队列的尾部,换句话说,“傀儡”节点在头部和尾部之间创建了一个通道,是整个队列造成一个循环,这样就能够从任意一个节点的任意一个方向能遍历完整的队列。
一样LinkedList也是一个没有容量限制的队列,所以入队列(无论是从头部仍是尾部)总能成功。
上面描述的ArrayDeque和LinkedList是两种不一样方式的实现,一般在遍历和节省内存上ArrayDeque更高效(索引更快,另外不须要Entry对象),可是在队列扩容下LinkedList更灵活,由于不须要复制原始的队列,某些状况下可能更高效。
一样须要注意的上述两个实现都不是线程安全的,所以只适合在单线程环境下使用,下面章节要介绍的LinkedBlockingDeque就是线程安全的可阻塞的Deque。事实上也应该是功能最强大的Queue实现,固然了实现起来也许会复杂一点。