什麼是Queue集合? 答:Queue用於模擬隊列這種數據結構。隊列通常是指“先進先出(FIFO)”的容器。隊列的頭部保存在隊列中存放時間最長的元素,尾部保存存放時間最短的元素。新元素插入到隊列的尾部,取出元素會返回隊列頭部的元素。通常,隊列不允許隨機訪問隊列中的元素。 Queue介面中定義瞭如下的 ...
什麼是Queue集合?
答:Queue用於模擬隊列這種數據結構。隊列通常是指“先進先出(FIFO)”的容器。隊列的頭部保存在隊列中存放時間最長的元素,尾部保存存放時間最短的元素。新元素插入到隊列的尾部,取出元素會返回隊列頭部的元素。通常,隊列不允許隨機訪問隊列中的元素。
Queue介面中定義瞭如下的幾個方法:
void add(Object e): 將指定元素插入到隊列的尾部。
object element(): 獲取隊列頭部的元素,但是不刪除該元素。
boolean offer(Object e): 將指定的元素插入此隊列的尾部。當使用容量有限的隊列時,此方法通常比add(Object e)有效。
Object peek(): 返回隊列頭部的元素,但是不刪除該元素。如果隊列為空,則返回null。
Object poll(): 返回隊列頭部的元素,並刪除該元素。如果隊列為空,則返回null。
Object remove(): 獲取隊列頭部的元素,並刪除該元素。
Queue介面有一個PriorityQueue實現類。除此之外,Queue還有一個Deque介面,Deque代表一個“雙端隊列”,雙端隊列可以同時從兩端刪除或添加元素,因此Deque可以當作棧來使用。java為Deque提供了ArrayDeque實現類和LinkedList實現類。
1.PriorityQueue實現類
PriorityQueue是一種比較標準的隊列實現類,而不是絕對標準的。這是因為PriorityQueue保存隊列元素的順序不是按照元素添加的順序來保存的,而是在添加元素的時候對元素的大小排序後再保存的。因此在PriorityQueue中使用peek()或pool()取出隊列中頭部的元素,取出的不是最先添加的元素,而是最小的元素。
public class PriorityQueueTest { public static void main(String[] args){ PriorityQueue pq = new PriorityQueue(); pq.offer(6); pq.add(-3); pq.add(20); pq.offer(18); //輸出:[-3, 6, 20, 18] System.out.println(pq); } }
PriorityQueue不允許插入null元素,它還需要對隊列元素進行排序,PriorityQueue有兩種排序方式:
自然排序:採用自然排序的PriorityQueue集合中的元素必須實現Comparator介面,而且應該是一個類的多個實例,否則可能導致ClassCastException異常。
定製排序:創建PriorityQueue隊列時,傳入一個Comparable對象,該對象負責對所有隊列中的所有元素進行排序。採用定製排序不要求必須實現Comparator介面。
2.Dueue介面與ArrayDeque實現類
Deque介面是Queue介面的子介面,它代表一個雙端隊列,Deque定義了一些方法:
void addFirst(Object e): 將指定元素添加到雙端隊列的頭部。
void addLast(Object e): 將指定元素添加到雙端隊列的尾部。
Iteratord descendingItrator(): 返回該雙端隊列對應的迭代器,該迭代器以逆向順序來迭代隊列中的元素。
Object getFirst(): 獲取但不刪除雙端隊列的第一個元素。
Object getLast(): 獲取但不刪除雙端隊列的最後一個元素。
boolean offFirst(Object e): 將指定元素添加到雙端隊列的頭部。
boolean offLast(OBject e): 將指定元素添加到雙端隊列的尾部。
Object peekFirst(): 獲取但不刪除雙端隊列的第一個元素;如果雙端隊列為空,則返回null。
Object PeekLast(): 獲取但不刪除雙端隊列的最後一個元素;如果雙端隊列為空,則返回null。
Object pollFirst(): 獲取並刪除雙端隊列的第一個元素;如果雙端隊列為空,則返回null。
Object pollLast(): 獲取並刪除雙端隊列的最後一個元素;如果雙端隊列為空,則返回null。
Object pop()(棧方法): pop出該雙端隊列所表示的棧的棧頂元素。相當於removeFirst()。
void push(Object e)(棧方法): 將一個元素push進該雙端隊列所表示的棧的棧頂。相當於addFirst()。
Object removeFirst(): 獲取並刪除該雙端隊列的第一個元素。
Object removeFirstOccurence(Object o): 刪除該雙端隊列的第一次出現的元素o。
Object removeLast(): 獲取並刪除該雙端隊列的最後一個元素o。
Object removeLastOccurence(Object o): 刪除該雙端隊列的最後一次出現的元素o。
public class ArrayDequeTest { public static void main(String[] args){ ArrayDeque queue = new ArrayDeque(); queue.offer("春"); queue.offer("夏"); queue.offer("秋"); //輸出:[春, 夏, 秋] System.out.println(queue); //輸出:春 System.out.println(queue.peek()); //輸出:[春, 夏, 秋] System.out.println(queue); //輸出:春 System.out.println(queue.poll()); //輸出:[夏, 秋] System.out.println(queue); } }
//將雙端隊列當做棧 public class DequeStack { public static void main(String[] args){ ArrayDeque stack = new ArrayDeque(); stack.push("春"); stack.push("夏"); stack.push("秋"); //輸出:[秋, 夏, 春] System.out.println(stack); //輸出:秋 System.out.println(stack.peek()); //輸出:[秋, 夏, 春] System.out.println(stack); //輸出:秋 System.out.println(stack.pop()); //輸出:[夏, 春] System.out.println(stack); } }
3.LinkedList實現類
LinkedList是List介面的實現類,因此它可以是一個集合,可以根據索引來隨機訪問集合中的元素。此外,它還是Duque介面的實現類,因此也可以作為一個雙端隊列,或者棧來使用。
LinkedList與ArrayList,ArrayDeque的實現機制完全不同,ArrayList和ArrayDeque內部以數組的形式來保存集合中的元素,因此隨機訪問集合元素時有較好的性能;而LinkedList以鏈表的形式來保存集合中的元素,因此隨機訪問集合元素時性能較差,但是插入和刪除元素時性能比較出色(只需改變指針所指的地址即可),需要指出的是,雖然Vector也是以數組的形式來存儲集合但因為它實現了線程同步(而且實現的機制不好),故各方面的性能都比較差。