日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ava容器类4:Queue深入解读

發(fā)布時(shí)間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ava容器类4:Queue深入解读 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Collection的其它兩大分支:List和Set在前面已近分析過,這篇來分析一下Queue的底層實(shí)現(xiàn)。

前三篇關(guān)于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 操作外,隊(duì)列還提供其他的

插入、提取和檢查

操作。每個(gè)方法都存在兩種形式:

一種拋出異常(操作失敗時(shí)),另一種返回一個(gè)特殊值(null 或 false,具體取決于操作)。

插入操作的后一種形式是用于專門為有容量限制的 Queue 實(shí)現(xiàn)設(shè)計(jì)的;在大多數(shù)實(shí)現(xiàn)中,插入操作不會失敗。 ?

AbstractQueue


AbstractQueue中實(shí)現(xiàn)了queue和Collection中部分函數(shù),比較簡單,源碼如下:

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;} }

從上面的調(diào)用關(guān)系可以看出來,Queue的解釋中哪些是會拋出異常的調(diào)用,哪些是不會拋出異常的調(diào)用接口。

Deque


一個(gè)線性 collection,支持在兩端插入和移除元素。名稱 deque 是“double ended queue(雙端隊(duì)列)”的縮寫,通常讀為“deck”。大多數(shù) Deque 實(shí)現(xiàn)對于它們能夠包含的元素?cái)?shù)沒有固定限制,但此接口既支持有容量限制的雙端隊(duì)列,也支持沒有固定大小限制的雙端隊(duì)列。(java 1.6版本中的家扣,1.8中接口有變動(dòng),但是大概含義相似)

在Java容器類1中介紹了LinkedList,鏈表類其實(shí)實(shí)現(xiàn)了 Deque的接口,所以鏈表支持從頭部和尾部添加和移除元素。

ArrayDeque


因?yàn)殒湵淼拇鎯Y(jié)構(gòu)可能比較簡單,這里介紹一下ArrayDeque,它的里面存儲元素使用一個(gè)數(shù)組。 作為一個(gè)雙端隊(duì)列的數(shù)組,涉及到擴(kuò)容和元素的拷貝的邏輯可能比較復(fù)雜些。

看一下里面的幾個(gè)構(gòu)造函數(shù):

public ArrayDeque() {elements =

new Object[16];

}public ArrayDeque(int numElements) {

allocateElements(numElements);

}public ArrayDeque(Collection<? extends E> c) {allocateElements(c.size());addAll(c);}

從構(gòu)造函數(shù)可以看出默認(rèn)的會分配一個(gè)長度為16的數(shù)組。同時(shí),也支持指定大小的隊(duì)列(這里的allocateElements函數(shù)之前在

java容器類2:Map及HashMap深入解讀? 中已經(jīng)深入分析過,是個(gè)非常精妙的函數(shù))。下面看一下到底是如何實(shí)現(xiàn)插入?又是如何自動(dòng)擴(kuò)充數(shù)組的?

ArrayQueue中維護(hù)了兩個(gè)成員變量:head和tail分別代表 隊(duì)列的頭和尾在數(shù)組中的下標(biāo)。

/*** 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;

在隊(duì)列的首部添加元素:

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(); }

由構(gòu)造函數(shù)和數(shù)組分配的函數(shù)可以知道,數(shù)組的長度肯定是一個(gè)2的冪次方的一個(gè)整數(shù)。

當(dāng)head為大于0的整數(shù)時(shí),在頭部插入很簡單,將head前一個(gè)元素賦值為e就可以了。那么當(dāng)head為0時(shí),怎么計(jì)算的?由上面可以看出會插入到數(shù)組的尾部。所以ArrayDeque相當(dāng)于在一個(gè)圓環(huán)上,規(guī)定一個(gè)頭一個(gè)尾作為隊(duì)列的前后(將數(shù)組的首位相連)。

在最后位置添加元素的原理和在首部添加相似。注意判斷是否已滿的 判斷,這里不再分析。

當(dāng)隊(duì)列已經(jīng)滿后,會將數(shù)組的長度double。由于數(shù)組是不能自由擴(kuò)張的,所以doubleCapacity函數(shù)應(yīng)該是分配一個(gè)更大的數(shù)組,并將原來的元素拷貝進(jìn)去,這里不再分析。

總的來說雙端隊(duì)列ArrayDeque是在數(shù)組的基礎(chǔ)之上實(shí)現(xiàn),原理和實(shí)現(xiàn)都不算復(fù)雜,但是很多邊界調(diào)節(jié)等細(xì)節(jié)可以斟酌。

BlockingQueue


BlockingQueue是concurrent包下面的,后續(xù)打算寫一個(gè)系列文章專門分析concurrent包下面的類,及一些多線程相關(guān)的東西。

PriorityQueue


優(yōu)先級隊(duì)列是一個(gè)可以排序的隊(duì)列。內(nèi)部是一個(gè)最大堆,大部分人應(yīng)該了解堆排序,所以對最大堆應(yīng)該不會陌生。

每次讀取元素都是讀取最大的元素(默認(rèn)情況下)。

對外的接口有如下:

方法名功能描述
add(E e)添加元素
clear()清空
contains(Object o)檢查是否包含當(dāng)前參數(shù)元素
offer(E e)添加元素
peek()讀取元素,(不刪除)
poll()取出元素,(刪除)
remove(Object o)刪除指定元素
size()返回長度

PriorityQueue 默認(rèn)是一個(gè)最大堆結(jié)構(gòu),如果想構(gòu)造一個(gè)最小堆:

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;}});

關(guān)于堆的數(shù)據(jù)結(jié)構(gòu)部分這里不再分析可以參考:https://www.cnblogs.com/tstd/p/5125949.html

c++版的優(yōu)先級隊(duì)列分析:優(yōu)先級隊(duì)列用法詳解(priority_queue)

由于是通過數(shù)組保存數(shù)據(jù),所以優(yōu)先級隊(duì)列也會涉及到容量的擴(kuò)充等,和HashMap/Setting/Collection的擴(kuò)容原理相同,甚至更簡單,不再分析。PriorityQueue內(nèi)部的操作都是在最大堆的基礎(chǔ)上展開的,閱讀堆的數(shù)據(jù)結(jié)構(gòu)相關(guān)資料便可了解。

參考:

http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/Deque.html

http://www.cnblogs.com/NeilZhang/p/5650226.html

總結(jié)

以上是生活随笔為你收集整理的ava容器类4:Queue深入解读的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。