ava容器类4:Queue深入解读
Collection的其它兩大分支:List和Set在前面已近分析過,這篇來分析一下Queue的底層實現。
前三篇關于Java容器類的文章:
java容器類1:Collection,List,ArrayList,LinkedList深入解讀
java容器類2:Map及HashMap深入解讀
java容器類3:set/HastSet/MapSet深入解讀
Queue
public interface Queue<E> extends Collection<E> {boolean add(E var1);boolean offer(E var1);E remove();E poll();E element();E peek(); } 這就是Queue接口的代碼,相比于List或者Set簡潔明了很多。下面介紹一下它里面接口的含義: 在處理元素前用于保存元素的 collection。除了基本的 Collection 操作外,隊列還提供其他的
插入、提取和檢查
操作。每個方法都存在兩種形式:一種拋出異常(操作失敗時),另一種返回一個特殊值(null 或 false,具體取決于操作)。
插入操作的后一種形式是用于專門為有容量限制的 Queue 實現設計的;在大多數實現中,插入操作不會失敗。 ?AbstractQueue
AbstractQueue中實現了queue和Collection中部分函數,比較簡單,源碼如下:
public abstract class AbstractQueue<E> extends AbstractCollection<E>implements Queue<E> { protected AbstractQueue() {} public boolean add(E e) {if (offer(e))return true;elsethrow new IllegalStateException("Queue full");}public E remove() {E x = poll();if (x != null)return x;elsethrow new NoSuchElementException();}public E element() {E x = peek();if (x != null)return x;elsethrow new NoSuchElementException();}public void clear() {while (poll() != null);}public boolean addAll(Collection<? extends E> c) {if (c == null)throw new NullPointerException();if (c == this)throw new IllegalArgumentException();boolean modified = false;for (E e : c)if (add(e))modified = true;return modified;} }從上面的調用關系可以看出來,Queue的解釋中哪些是會拋出異常的調用,哪些是不會拋出異常的調用接口。
Deque
一個線性 collection,支持在兩端插入和移除元素。名稱 deque 是“double ended queue(雙端隊列)”的縮寫,通常讀為“deck”。大多數 Deque 實現對于它們能夠包含的元素數沒有固定限制,但此接口既支持有容量限制的雙端隊列,也支持沒有固定大小限制的雙端隊列。(java 1.6版本中的家扣,1.8中接口有變動,但是大概含義相似)
在Java容器類1中介紹了LinkedList,鏈表類其實實現了 Deque的接口,所以鏈表支持從頭部和尾部添加和移除元素。
ArrayDeque
因為鏈表的存儲結構可能比較簡單,這里介紹一下ArrayDeque,它的里面存儲元素使用一個數組。 作為一個雙端隊列的數組,涉及到擴容和元素的拷貝的邏輯可能比較復雜些。
看一下里面的幾個構造函數:
public ArrayDeque() {elements =new Object[16];
}public ArrayDeque(int numElements) {allocateElements(numElements);
}public ArrayDeque(Collection<? extends E> c) {allocateElements(c.size());addAll(c);}從構造函數可以看出默認的會分配一個長度為16的數組。同時,也支持指定大小的隊列(這里的allocateElements函數之前在
java容器類2:Map及HashMap深入解讀? 中已經深入分析過,是個非常精妙的函數)。下面看一下到底是如何實現插入?又是如何自動擴充數組的?
ArrayQueue中維護了兩個成員變量:head和tail分別代表 隊列的頭和尾在數組中的下標。
/*** The index of the element at the head of the deque (which is the* element that would be removed by remove() or pop()); or an* arbitrary number equal to tail if the deque is empty.*/transient int head;/*** The index at which the next element would be added to the tail* of the deque (via addLast(E), add(E), or push(E)).*/transient int tail;在隊列的首部添加元素:
public void addFirst(E e) {if (e == null)throw new NullPointerException();elements[head = (head - 1) & (elements.length - 1)] = e;
if (head == tail)doubleCapacity();
}public void
addLast(E e) {if
(e ==null
)throw new
NullPointerException();elements[tail] = e;if
( (tail = (tail + 1) & (elements.length - 1)) == head)doubleCapacity(); }由構造函數和數組分配的函數可以知道,數組的長度肯定是一個2的冪次方的一個整數。
當head為大于0的整數時,在頭部插入很簡單,將head前一個元素賦值為e就可以了。那么當head為0時,怎么計算的?由上面可以看出會插入到數組的尾部。所以ArrayDeque相當于在一個圓環上,規定一個頭一個尾作為隊列的前后(將數組的首位相連)。
在最后位置添加元素的原理和在首部添加相似。注意判斷是否已滿的 判斷,這里不再分析。
當隊列已經滿后,會將數組的長度double。由于數組是不能自由擴張的,所以doubleCapacity函數應該是分配一個更大的數組,并將原來的元素拷貝進去,這里不再分析。
總的來說雙端隊列ArrayDeque是在數組的基礎之上實現,原理和實現都不算復雜,但是很多邊界調節等細節可以斟酌。
BlockingQueue
BlockingQueue是concurrent包下面的,后續打算寫一個系列文章專門分析concurrent包下面的類,及一些多線程相關的東西。
PriorityQueue
優先級隊列是一個可以排序的隊列。內部是一個最大堆,大部分人應該了解堆排序,所以對最大堆應該不會陌生。
每次讀取元素都是讀取最大的元素(默認情況下)。
對外的接口有如下:
| add(E e) | 添加元素 |
| clear() | 清空 |
| contains(Object o) | 檢查是否包含當前參數元素 |
| offer(E e) | 添加元素 |
| peek() | 讀取元素,(不刪除) |
| poll() | 取出元素,(刪除) |
| remove(Object o) | 刪除指定元素 |
| size() | 返回長度 |
PriorityQueue 默認是一個最大堆結構,如果想構造一個最小堆:
private static final int DEFAULT_INITIAL_CAPACITY = 11; PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(DEFAULT_INITIAL_CAPACITY, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}});關于堆的數據結構部分這里不再分析可以參考:https://www.cnblogs.com/tstd/p/5125949.html
c++版的優先級隊列分析:優先級隊列用法詳解(priority_queue)
由于是通過數組保存數據,所以優先級隊列也會涉及到容量的擴充等,和HashMap/Setting/Collection的擴容原理相同,甚至更簡單,不再分析。PriorityQueue內部的操作都是在最大堆的基礎上展開的,閱讀堆的數據結構相關資料便可了解。
參考:
http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/Deque.html
http://www.cnblogs.com/NeilZhang/p/5650226.html
總結
以上是生活随笔為你收集整理的ava容器类4:Queue深入解读的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 比特币跌穿1.8万美元 15万人爆仓!特
- 下一篇: 如何收缩超大的SharePoint_Co