Java—Queue隊列詳解(Deque/PriorityQueue/Deque/ArrayDeque/LinkedList)


Queue

Queue隊列介紹

  Queue是用於模擬隊列的,啥叫隊列?隊列就是排隊的意思,比如排隊結賬,先進入隊伍中,先排到先付賬走人;后排到的,進入隊伍,等前面的人出隊伍后,再跟在后面付錢出隊。符合“先進先出FIFO”的規則,是一種線性表。插入在一端,刪除則在另一端。入隊(offer)在隊尾,出隊(poll)在隊頭。
  Queue接口有實現類PriorityQueue,有另一個雙端隊列接口Deque。

Queue隊列進出示意圖

隊列進出示意圖

Queue常用方法

  PriorityQueue擁有QueueCollection的方法。下面主要介紹一些常用方法:

  • boolean add(E e);:將指定元素加入到隊列的尾部。
  • E element();:獲取隊列頭部的元素,但是不刪除該元素。
  • boolean offer(E e);:將指定元素加入到隊列的尾部。
  • E peek();:獲取隊列頭部的元素,但是不刪除元素;若隊列為空,返回null。
  • E poll();:獲取隊列頭部的元素,並刪除該元素。若隊列為空,返回null。
  • E remove();:獲取隊列頭部的元素,並刪除該元素。若隊列為空,拋異常。

PriorityQueue

PriorityQueue概述

  PriorityQueue是Queue隊列實現類,PriorityQueue保存隊列元素的順序不是按照加入隊列的順序,而是按照隊列元素的大小進行重新排序。當調用peek()或者poll()方法獲取隊列元素時,獲取的是隊列最小元素,而不是先入隊列的元素。有點反先入先出規則

PriorityQueue示例

1)運行主類:

public class DemoApplication {

    public static void main(String[] args) {

        PriorityQueue priorityQueue = new PriorityQueue();
        priorityQueue.offer(5);
        priorityQueue.offer(-1);
        priorityQueue.offer(3);
        priorityQueue.offer(7);

        //查看入隊順序
        System.out.println("隊列輸出:" + priorityQueue);

        //peek方法獲取隊頭元素但是不刪除元素
        System.out.println("peek()方法獲取隊頭:" + priorityQueue.peek());

        //查看第一個元素即為最小元素
        System.out.println("第一個隊列元素出隊:" + priorityQueue.poll());
        System.out.println("第二個隊列元素出隊:" + priorityQueue.poll());
        System.out.println("第三個隊列元素出隊:" + priorityQueue.poll());
        System.out.println("第四個隊列元素出隊:" + priorityQueue.poll());
        System.out.println("null隊列:" + priorityQueue.poll());
        
    }

}

2)運行結果:

隊列輸出:[-1, 5, 3, 7]
peek()方法獲取隊頭:-1
第一個隊列元素出隊:-1
第二個隊列元素出隊:3
第三個隊列元素出隊:5
第四個隊列元素出隊:7
null隊列:null

Deque

Deque雙端隊列介紹

  Deque是Queue子接口,是雙端隊列。可以同時從兩端(隊列頭部和尾部)添加、刪除元素。所以可以用來實現棧的數據結構。有兩個實現類(ArrayDequeLinkedList

Deque常用方法

  • void addFirst(E e):將指定元素插入該雙端隊列的頭部,比較重要,下面很多方法頭部插入內部實現都是通過這個來實現的,如offerFirst()。
  • void addLast(E e):將指定元素插入該雙端隊列的尾部。比較重要,下面添加到尾部插入內部實現都是通過這個來實現的,如offerLast()。
  • E getFirst():獲取但不刪除雙端隊列的第一個元素。
  • E getLast():獲取但不刪除雙端隊列的最后一個元素。
  • E removeFirst():獲取並刪除該雙端隊列的第一個元素。棧的出隊列方法pop()也是通過該方法實現的。
  • E removeLast():獲取並刪除該雙端隊列的最后一個元素。
  • Iterator<E> descendingIterator():返回雙端隊列的迭代器,逆向順序迭代元素。
  • boolean offerFirst(E e):將指定元素插入該雙端隊列的頭部。
    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }
  • boolean offerLast(E e):將指定元素插入該雙端隊列的尾部。
    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }
  • E peekFirst():獲取但不刪除該雙端隊列的第一個元素;若隊列為空,則返回null。
    public E peekFirst() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
     }
  • E peekLast():獲取但不刪除該雙端隊列的最后一個元素;若隊列為空,則返回null。
    public E peekLast() {
        final Node<E> l = last;
        return (l == null) ? null : l.item;
    }
  • E pollFirst():獲取並刪除該雙端隊列的第一個元素;若隊列為空,則返回null。
    public E pollFirst() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }
  • E pollLast():獲取並刪除該雙端隊列的最后一個元素;若隊列為空,則返回null。
    public E pollLast() {
        final Node<E> l = last;
        return (l == null) ? null : unlinkLast(l);
    }
  • E pop():棧方法,pop出該雙端隊列表示棧的棧頂元素,等價於removeFirst()方法。
    public E pop() {
        return removeFirst();
    }
  • void push(E e):棧方法,push元素進入該雙端隊列表示棧的棧頂,等價於addFist()方法。
    public void push(E e) {
        addFirst(e);
    }
  • boolean removeFirstOccurrence(Object o):刪除該雙端隊列的第一次出現的元素o,底層通過remove()方法實現。
    public boolean removeFirstOccurrence(Object o) {
        return remove(o);
    }
  • boolean removeLastOccurrence(Object o):刪除該涮短隊列的最后一次出現的元素o。

ArrayDeque

ArrayDeque概述

  ArrayDeque底層實現類似於ArrayList,都是通過動態、可分配的Object[]數組來實現元素存儲,當集合元素超過數組容量,會重新分配一個新的數組來存儲集合元素。

ArrayDeque示例

1)運行主類

public class DemoApplication {
    public static void main(String[] args) {
        //可以作為棧來使用,先進后出
        ArrayDeque<String> arrayDeque = new ArrayDeque<>();
        arrayDeque.push("book01");
        arrayDeque.push("book03");
        arrayDeque.push("book02");
        arrayDeque.push("book04");

        System.out.println("原棧:" + arrayDeque);

        System.out.println("獲取頭部元素,但不刪除該元素,peek(): " + arrayDeque.peek());
        System.out.println("獲取頭部元素,且刪除該元素,pop(): " +arrayDeque.pop());
        System.out.println("獲取第一個元素,但不刪除:" + arrayDeque.getFirst());
        System.out.println("獲取最后一個元素,但不刪除:" + arrayDeque.getLast());

        System.out.println("在雙端隊列頭部插入元素:" + arrayDeque.offerFirst("booknew01"));
        System.out.println("在雙端隊列尾部插入元素:" + arrayDeque.offerLast("booknew02"));
        System.out.println("新棧:" + arrayDeque);

    }

}

2)運行結果

原棧:[book04, book02, book03, book01]
獲取頭部元素,但不刪除該元素: book04
獲取頭部元素,且刪除該元素: book04
獲取第一個元素,但不刪除:book02
獲取最后一個元素,但不刪除:book01
true
true
新棧:[booknew01, book02, book03, book01, booknew02]

LinkedList

LinkedList概述

  LinkedList實現List,同時也實現了Deque,可以當做雙端隊列來使用,可以當做“棧”或“隊列”使用。
  LinkedList與ArrayList、ArrayDeque不同之處在於底層實現,LinkedList底層是通過鏈表的形式存儲元素,隨機訪問性能比較差,但是在插入刪除的時候性能比較好(只需要改變指針所指的地址就行)

Q&A

peek()和element()的異同

  • 同:peek()和element()都是在不移除的情況下返回隊頭;
  • 異:peek()方法在隊列為空時返回null,而element()會拋出NoSuchElementException異常。

poll()和remove()的異同

  • 同:poll()和remove()都是將移除並返回隊頭;
  • 異:poll()在隊列為空時返回null,而remove()會拋出NoSuchElementException異常。

隊列和棧區別?

隊列

  1. 隊列是按照先進先出FIFO原則進行操作元素的。
  2. 隊列是限定所有的插入只能在表的一端進行,而刪除在表的另一端進行的線性表。
  3. 表中允許插入的一端為隊尾,允許刪除的一端為隊頭。


4. 棧是一種特殊的線性表,是一種后進先出LIFO的結構;
5. 棧是先定僅在表尾插入和刪除運算的線性表,表尾即為棧頂,表頭稱為棧底。
6. 棧的物理存儲可以用熟悉順序存儲結構,也可以用鏈式存儲結構。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM