Java 队列 – Java 中的隊列

Java Queue 是 java.util 套件中可用的介面,並擴展了 java.util.Collection 介面。就像 Java List 一樣,Java Queue 是一個有序元素(或對象)的集合,但它執行插入和刪除操作的方式不同。我們可以使用 Queue 在處理這些元素之前存儲元素。

Java Queue

在這一部分,我們將討論 Java Queue 的一些重要點:

  • java.util.Queue 介面是 java.util.Collection 介面的一個子類。
  • 就像現實世界中的隊列一樣(例如,在銀行或自動取款機中),Queue 在隊列的末尾插入元素並從隊列的開頭刪除元素。
  • Java Queue 表示一個有序元素列表。
  • Java Queue 遵循先進先出(FIFO)的順序來插入和刪除元素。FIFO 意味著先進先出。
  • Java Queue 支持 Collection 介面的所有方法。
  • 最常用的 Queue 實現是 LinkedList、ArrayBlockingQueue 和 PriorityQueue。
  • BlockingQueues 不接受 null 元素。如果進行任何與 null 相關的操作,它將拋出 NullPointerException。
  • BlockingQueues 用於實現基於生產者/消費者的應用程序。
  • BlockingQueues 是線程安全的。
  • 所有在java.util套件中可用的佇列都是無界佇列,而在java.util.concurrent套件中可用的佇列都是有界佇列。
  • 所有的Deques都不是線程安全的。
  • ConcurrentLinkedQueue是一個基於鏈結節點的無界線程安全佇列。
  • 所有的佇列都支持在佇列尾部插入和在佇列頭部刪除,除了Deques。
  • Deques是佇列,但它們支持在兩端插入和刪除元素。

Java佇列類別圖

Java佇列介面擴展了Collection介面。Collection介面擴展了Iterable介面。一些常用的佇列實現類包括LinkedList、PriorityQueue、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue等。AbstractQueue提供了Queue介面的骨架實現,以減少實現Queue的工作量。

Java佇列方法

在本節中,我們將討論一些有用且常用的Java佇列方法:

  1. int size():獲取集合中元素的數量。
  2. boolean isEmpty():檢查Set是否為空。
  3. boolean contains(Object o):如果Set包含指定的元素,則返回true。
  4. Iterator iterator():返回此Set中元素的迭代器。元素以無特定順序返回。
  5. boolean removeAll(Collection c):從Set中移除指定集合中包含的所有元素(可選操作)。
  6. boolean retainAll(Collection c):只保留Set中包含在指定集合中的元素(可選操作)。
  7. void clear():從Set中移除所有元素。
  8. E remove(): Retrieves and removes the head of this queue.
  9. E poll(): Retrieves and removes the head of this queue, or returns null if this queue is empty.
  10. E peek(): Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.
  11. boolean offer(E e):如果立即插入指定的元素而不違反容量限制,則將其插入此隊列中。
  12. E element(): Retrieves, but does not remove, the head of this queue.
  13. boolean add(E e):如果立即插入指定的元素而不違反容量限制,則將其插入此隊列中。成功時返回true,如果當前沒有可用空間,則拋出IllegalStateException。
  14. Object[] toArray():返回包含此Set中所有元素的數組。如果Set對其元素返回迭代器的順序有任何保證,則此方法必須以相同的順序返回元素。

Java Queue基礎

當Java Queue擴展Java Collection時,它也支持所有Collection接口操作。讓我們在以下的例子中探索一些簡單的操作:

package com.journaldev.queue;
import java.util.*;

public class QueueExample {
   public static void main(String[] args) {
		
	Queue queue = new LinkedList<>();
	queue.add("one");
	queue.add("two");
	queue.add("three");
	queue.add("four");
	System.out.println(queue);
		
	queue.remove("three");
	System.out.println(queue);
	System.out.println("Queue Size: " + queue.size());
	System.out.println("Queue Contains element 'two' or not? : " + queue.contains("two"));

	// 清空隊列
	queue.clear();
   }
}

輸出:-

[one, two, three, four]
[one, two, four]
Queue Size: 3
Queue Contains element 'two' or not? : true

Java數組轉隊列

在這裡,我們可以探索如何使用“Collections.addAll()”方法將Java數組轉換為隊列,並提供一個簡單的示例。

import java.util.*;

public class ArrayToQueue {
    public static void main(String[] args) {
		
	String nums[] = {"one","two","three","four","five"};
	Queue<String> queue = new LinkedList<>();
	Collections.addAll(queue, nums);
	System.out.println(queue);
   }
}

輸出:- 當我們運行上述程序時,將獲得以下輸出:

[one, two, three, four, five]

Java隊列轉數組

在這裡,我們將探討如何使用“toArray()”方法將Java隊列轉換為Java數組,並提供一個簡單的示例。

import java.util.*;

public class QueueToArray {
   public static void main(String[] args) {
		
	Queue<String> queue = new LinkedList<>();
	queue.add("one");
	queue.add("two");
	queue.add("three");
	queue.add("four");
	queue.add("five");
		
	String strArray[] = queue.toArray(new String[queue.size()]);
	System.out.println(Arrays.toString(strArray)); 

   }
}

輸出:- 當我們運行上述程序時,將獲得以下輸出:

[one, two, three, four, five]

Java隊列常見操作

Java隊列支持Collection接口支持的所有操作以及一些其他操作。它以兩種形式支持幾乎所有操作。

  • 一組操作如果操作失敗會拋出異常。
  • 另一組操作如果操作失敗會返回特殊值。

以下表格簡要解釋了所有隊列的常見操作。

Operation Throws exception Special value
Insert add(e) offer(e)
Remove remove() poll()
Examine element() peek()

我們將在接下來的部分中逐個操作進行詳細討論,並提供一些有用的示例。

Java 隊列插入操作

在本節中,我們將詳細討論 Java 隊列插入操作,並提供一些有用的示例。如果此操作成功執行,它將返回“true”值。正如我們所知,隊列支持兩種形式的插入操作:

  • Queue.add(e):如果操作失敗,它會拋出異常。- Queue.offer(e):如果操作失敗,它會返回一個特殊值。

注意:-這裡的特殊值可以是“false”或“null”

隊列 add() 操作

add() 操作用於將新元素插入隊列中。如果成功執行插入操作,它將返回“true”值。否則,它會拋出 java.lang.IllegalStateException。讓我們開發一個簡單的示例來演示此功能。

import java.util.concurrent.*;

public class QueueAddOperation {
   public static void main(String[] args) {
		
	BlockingQueue<String> queue = new ArrayBlockingQueue<>(2);

	System.out.println(queue.add("one"));
	System.out.println(queue.add("two"));
	System.out.println(queue);
	System.out.println(queue.add("three"));
	System.out.println(queue);
   }
}

輸出:- 當我們執行上面的程式時,將獲得以下輸出:

true
true
[one, two]
Exception in thread "main" java.lang.IllegalStateException: Queue full

由於我們的佇列僅限於兩個元素,當我們嘗試使用BlockingQueue.add()添加第三個元素時,它會拋出如上所示的例外。

佇列offer()操作

offer()操作用於將新元素插入佇列。如果成功執行插入操作,它將返回“true”值。否則它將返回“false”值。讓我們開發一個簡單的範例來演示此功能。

import java.util.concurrent.*;

public class QueueOfferOperation {
   public static void main(String[] args) {
		
	BlockingQueue<String> queue = new ArrayBlockingQueue<>(2);

	System.out.println(queue.offer("one"));
	System.out.println(queue.offer("two"));
	System.out.println(queue);
	System.out.println(queue.offer("three"));
	System.out.println(queue);
   }
}

輸出:- 當我們執行上面的程式時,將獲得以下輸出:

true
true
[one, two]
false
[one, two]

由於我們的佇列僅限於兩個元素,當我們嘗試使用BlockingQueue.offer()操作添加第三個元素時,它將返回“false”值,如上所示。

Java佇列刪除操作

在這一部分中,我們將詳細討論Java佇列刪除操作,並提供一些有用的示例。如果成功執行,刪除操作將返回佇列的頭元素。由於我們知道,佇列支援兩種形式的刪除操作:

  • Queue.remove():
    如果操作失敗,它會拋出異常。- Queue.poll():
    如果操作失敗,它將返回一個特殊值。

注意:此處特殊值可能是“false”或“null”

隊列 remove() 操作

remove() 操作用於從隊列頭部刪除元素。如果成功執行刪除操作,將返回隊列的頭元素。否則,它會拋出 java.util.NoSuchElementException。讓我們開發一個簡單的示例來演示此功能。

import java.util.*;

public class QueueRemoveOperation 
{
   public static void main(String[] args) 
   {		
	Queue<String> queue = new LinkedList<>();
	queue.offer("one");
	queue.offer("two");		
	System.out.println(queue);		
	System.out.println(queue.remove());
	System.out.println(queue.remove());		
	System.out.println(queue.remove());		
   }
}

輸出:當我們運行上面的程序時,我們將獲得以下輸出:

[one, two]
one
two
Exception in thread "main" java.util.NoSuchElementException

由於我們的隊列只有兩個元素,當我們嘗試第三次調用 remove() 方法時,它會拋出上面顯示的異常。注意:Queue.remove(element) 用於從隊列中刪除指定的元素。如果成功執行刪除操作,它將返回“true”值。否則,它將返回“false”值。

隊列 poll() 操作

poll() 操作用於從隊列頭部刪除元素。如果成功執行刪除操作,它將返回隊列的頭元素。否則,它將返回“null”值。讓我們開發一個簡單的示例來演示此功能。

import java.util.*;

public class QueuePollOperation 
{
   public static void main(String[] args) 
   {		
	Queue<String> queue = new LinkedList<>();
	queue.offer("one");
	queue.offer("two");		
	System.out.println(queue);		
	System.out.println(queue.poll());
	System.out.println(queue.poll());		
	System.out.println(queue.poll());		
   }
}

輸出:- 當我們運行上面的程序時,我們將獲得以下輸出:

[one, two]
one
two
null

由於我們的隊列只有兩個元素,當我們嘗試第三次調用poll()方法時,它將返回null值,如上所示。

Java隊列檢查操作

在本節中,我們將詳細討論Java隊列檢查操作,並提供一些有用的示例。如果此操作成功執行,它將返回隊列的頭元素而不將其移除。正如我們所知,隊列支持以兩種形式進行檢查操作:

  • Queue.element():
    如果操作失敗,它會拋出一個異常。- Queue.peek():
    如果操作失敗,它將返回一個特殊值。

注意:- 這裡的特殊值可以是“false”或“null”

隊列元素()操作

element()操作用於從隊列的頭部檢索元素,而不將其移除。如果執行檢查操作成功,它將返回隊列的頭元素。否則,它將拋出java.util.NoSuchElementException。讓我們開發一個簡單的示例來演示此功能。

import java.util.*;

public class QueueElementOperation {
   public static void main(String[] args) {
		
	Queue<String> queue = new LinkedList<>();
	queue.add("one");
		
	System.out.println(queue.element());
	System.out.println(queue);
	queue.clear();
	System.out.println(queue.element());
   }
}

輸出:- 當我們運行上面的程序時,我們將獲得以下輸出:

one
[one]
Exception in thread "main" java.util.NoSuchElementException

如果我們嘗試在空佇列上調用element()方法,它將拋出如上所示的異常。

佇列 peek() 操作

peek() 操作用於從佇列頭部檢索元素,而不移除它。如果成功執行檢查操作,它將返回佇列的頭元素。否則,它將返回空值。讓我們開發一個簡單的示例來演示此功能。

import java.util.*;

public class QueuePeekOperation {
   public static void main(String[] args) {
		
	Queue<String> queue = new LinkedList<>();
	queue.add("one");
		
	System.out.println(queue.peek());
	System.out.println(queue);
	queue.clear();
	System.out.println(queue.peek());
   }
}

輸出:- 當我們運行上面的程序時,我們將得到以下輸出:

one
[one]
null

如果我們嘗試在空佇列上調用peek()方法,它將返回空值,但不會拋出如上所示的異常。

Java 佇列分類

在Java中,我們可以找到許多佇列實現。我們可以將它們大致分為以下兩類:

  • 有界佇列
  • 無界佇列

有界佇列是由容量限制的佇列,這意味著我們需要在創建時提供佇列的最大大小。例如,ArrayBlockingQueue(參見上一個例子)。無界佇列是指不受容量限制的佇列,這意味著我們不應該提供佇列的大小。例如,LinkedList(參見上一個例子)。所有在java.util包中可用的佇列都是無界佇列,而在java.util.concurrent包中可用的佇列都是有界佇列。換句話說,我們可以將它們廣泛地分為以下兩類:

  • 阻塞佇列
  • 非阻塞佇列

所有實現BlockingQueue接口的佇列都是阻塞佇列,其餘的都是非阻塞佇列。阻塞佇列會阻塞,直到完成任務或超時,而非阻塞佇列則不會。一些佇列是Deques,一些佇列是PriorityQueues。

阻塞佇列操作

除了佇列的兩種操作形式外,阻塞佇列還支持如下兩種形式的操作。

Operation Throws exception Special value Blocks Times out
Insert add(e) offer(e) put(e) offer(e, time, unit)
Remove remove() poll() take() poll(time, unit)
Examine element() peek() N/A N/A

某些操作會阻塞,直到完成任務,而其他操作則會阻塞,直到超時。這就是關於Java中佇列的快速概述。我希望這些Java佇列示例能幫助您開始進行佇列集合編程。如果您喜歡我的教程,有任何建議、問題或打字錯誤,請給我留言。謝謝。

Source:
https://www.digitalocean.com/community/tutorials/java-queue