Java中的集合Queue、LinkedList、PriorityQueue

Queue接口
  Queue用於模擬了隊列這種數據結構,隊列通常是指“先進先出”(FIFO)的容器。隊列的頭部保存在隊列中時間最長的元素,隊列的尾部保存在隊列中時間最短的元素。新元素插入(offer)到隊列的尾部,訪問元素(poll)操作會返回隊列頭部的元素。通常,隊列不容許隨機訪問隊列中的元素。

Queue接口中定義瞭如下幾個方法:

void add(Object e);   //將指定元素加入此隊列的尾部。
Object element();   //獲取隊列頭部的元素,但是不刪除該元素。
boolean offer(Object e); //將指定元素加入此隊列的尾部。當使用有容量限制的隊列時,此方法通常比add(Object e)方法更好。
Object peek();    //獲取隊列頭部的元素,但是不刪除該元素,如果此隊列爲空,則返回null。
Object poll(); //獲取隊列頭部的元素,並刪除該元素,如果此隊列爲空,則返回null。
Object remove();   //獲取隊列頭部的元素,並刪除該元素。
  Queue有兩個常用的實現類:LinkedList和PriorityQueue,下面分別介紹這兩個實現類。

LinkedList
  LinkedList類是一個比較奇怪的類,它即是List接口的實現類,這意味着它是一個List集合,可以根據索引來隨機訪問集合中的元素。除此之外,LinkedList還實現了Deque接口,Deque接口是Queue接口的子接口,它代表一個雙向隊列,Deque接口裏定義了一些可以雙向操作隊列的方法:

void addFirst(Object e); //將指定元素插入該雙向隊列的開頭。
void addLast(Object e);  //將指定元素插入該雙向隊列的末尾。
Iterator descendingIterator(); //返回以該雙向隊列對應的迭代器,該迭代器將以逆向順序來迭代隊列中的元素。
Object getFirst();      //獲取、但不刪除雙向隊列的第一個元素。
Object getLast();   //獲取、但不刪除雙向隊列的最後一個元素。
boolean offerFirst(Object e);//將指定元素插入該雙向隊列的開頭
boolean offerLast(Object e);//將指定元素插入該雙向隊列的結尾
Object peekFirst(); //獲取、但不刪除雙向隊列的第一個元素;如果此雙端隊列爲空,則返回null。
Object peekLast(); //獲取、但不刪除該雙向隊列的最後一個元素;如果此雙端隊列爲空,則返回null。
Object pollFirst(); //獲取、並刪除雙向隊列的第一個元素;如果此雙端隊列爲空,則返回null。
Object pollLast(); //獲取、並刪除雙向隊列的最後一個元素,如果此雙端隊列爲空,則返回null。
Object pop(); //pop出該雙向隊列所表示的棧中第一個元素。
void push(Object e); //將一個元素push進該雙向隊列所表示的棧中。
Object removeFirst(); //獲取、並刪除該雙向隊列的第一個元素。
Object removeFirstOccurrence(Object e); //刪除該雙向隊列的第一次的出現元素e。
removeLast();   //獲取、並刪除該雙向隊列的最後一個元素。
removeLastOccurrence(Object e); //刪除該雙向隊列的最後一次的出現元素e
    從以上方法可以看出,LinkedList不僅可以當成雙向隊列使用,也可以當成“棧”使用,因爲該類還包含了pop(出棧)和push(入棧)兩個方法。除此之外,LinkedList實現了List接口,所以還被當成List使用。

建議:

  1. 如果需要遍歷List集合元素,對於ArrayList、Vector集合,則應該使用隨機訪問方法(get)來遍歷集合元素,這樣性能更好,對於LinkedList集合,則應該採用迭代器(Iterater)來遍歷集合元素。
  2. 如果需要經常執行插入、刪除操作來改變List集合大小,則應該使用LinkedList集合,而不是ArrayList。使用ArrayList、Vector集合將需要經常重新分配內存數組的大小,其時間開銷往往是使用LinkedList時時間開銷的幾十倍,效果很差。
    如果有多條線程需要同時訪問List集合中的元素,可以考慮使用Vector這個同步實現。

PriorityQueue實現類

PriorityQueue是一個比較標準的隊列實現類,之所以說它是比較標準的隊列實現,而不是絕對標準的隊列實現是因爲:PriorityQueue保存隊列元素的順序並不是按加入隊列的順序,而是按隊列元素的大小進行重新排序。
因此當調用peek方法活着pull方法來取出隊列中的元素時,並不是取出最先進入隊列的元素,而是取出隊列中最小的元素。從這個意義上看,PriorityQueue已經違反了隊列的最基本原則:先進先出(FIFO)。下面程序示範了PriorityQueue隊列的用法。

public class Test {
    public static void main(String[] args){
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
            pq.offer(3);
            pq.offer(-6);
            pq.offer(9);
            //打印結果爲[-6, 3, 9]
            System.out.println(pq);
            //打印結果爲-6
            System.out.println(pq.peek());
            //打印結果爲-6
            System.out.println(pq.poll());
    }
}

PriorityQueue不允許插入null元素,它還需要對隊列元素進行排序,隊列元素有兩種排序方式:自然排序、定製排序; 關於使用自然排序和定製排序與前面講到的TreeSet集合一樣。

優先隊列(priority queue)

優先級隊列 是不同於先進先出隊列的另一種隊列。每次從隊列中取出的是具有最高優先權的元素。

首先它是一個隊列,但是它強調了“優先”二字,所以,已經不能算是一般意義上的隊列了,它的“優先”意指取隊首元素時,有一定的選擇性,即根據元素的屬性選擇某一項值最優的出隊~

關於priority_queue
1,關於STL中的priority_queue:確定用top()查看頂部元素時,該元素是具有最高優先級的一個元素. 調用pop()刪除之後,將促使下一個元素進入該位置.
2,如同stack和queue,priority_queue是一個基於基本序列容器進行構建的適配器,默認的序列器是vector。

priority_queue<Type,Container,Compare> //compare默認是less

常用的操作如下:

empty() 如果優先隊列爲空,則返回真
pop() 刪除第一個元素
push() 加入一個元素
size() 返回優先隊列中擁有的元素的個數
top() 返回優先隊列中有最高優先級的元素

但是在使用時必須注意:priority_queue放置元素時,不會判斷元素是否重複。(因爲在模板的第二個參數時順序容器,不能保證元素的唯一性)此外可以替代默認的Compare函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章