java基礎 - 14 Java的Deque之Deque、BlockingDeque、LinkedBlockingDeque、ArrayDeque

Java 中的 Deque(雙端隊列)是一種具有隊列和棧特性的數據結構,它允許在兩端進行插入和刪除操作。Deque 接口是 Java 集合框架中的一部分,它定義了雙端隊列的基本操作。

BlockingDeque 接口: BlockingDeque 接口是 Deque 接口的子接口,它表示一個支持阻塞操作的雙端隊列。它定義了一些阻塞方法,如 putFirst(), putLast(), takeFirst(), takeLast() 等,這些方法在隊列滿或空時會阻塞線程。

LinkedBlockingDeque 類: LinkedBlockingDeque 類是 BlockingDeque 接口的一個實現,它基于鏈表實現了一個無界的阻塞雙端隊列。它支持并發訪問,并提供了阻塞的插入和刪除操作。由于它是無界隊列,因此可以根據需要添加任意數量的元素。

ArrayDeque 類: ArrayDeque 類是 Deque 接口的一個實現,它基于數組實現了一個雙端隊列。它支持并發訪問,并提供了高效的插入和刪除操作。ArrayDeque 是一個動態調整大小的數組,可以根據需要自動增加或縮小容量。

Deque

在這里插入圖片描述

Deque 接口: Deque 接口是 Java 集合框架中雙端隊列的根接口。它擴展了 Queue 接口,并添加了從兩端操作隊列的方法,如 addFirst(), addLast(), removeFirst(), removeLast() 等。

  • addFirst(E e):在雙端隊列的開頭插入指定元素。
  • addLast(E e):在雙端隊列的末尾插入指定元素。
  • removeFirst():移除并返回雙端隊列的第一個元素。
  • removeLast():移除并返回雙端隊列的最后一個元素。
  • getFirst():獲取雙端隊列的第一個元素,但不移除。
  • getLast():獲取雙端隊列的最后一個元素,但不移除。
  • peekFirst():獲取雙端隊列的第一個元素,如果隊列為空則返回 null。
  • peekLast():獲取雙端隊列的最后一個元素,如果隊列為空則返回 null。

在這里插入圖片描述
Deque 接口有多個實現類,常用的有:

  • ArrayDeque:基于數組實現的雙端隊列,它是一個動態調整大小的數組,可以根據需要自動增加或縮小容量。
  • LinkedList:基于鏈表實現的雙端隊列,它提供了高效的插入和刪除操作,但訪問元素的性能較低。
  • LinkedBlockingDeque:基于鏈表實現的無界阻塞雙端隊列,它支持并發訪問,并提供了阻塞的插入和刪除操作。
import java.util.Deque;
import java.util.ArrayDeque;public class Main {public static void main(String[] args) {Deque<Integer> deque = new ArrayDeque<>();deque.addFirst(1);deque.addLast(2);deque.addFirst(3);System.out.println(deque); // 輸出 [3, 1, 2]int first = deque.removeFirst();System.out.println(first); // 輸出 3int last = deque.removeLast();System.out.println(last); // 輸出 2int peekFirst = deque.peekFirst();System.out.println(peekFirst); // 輸出 1int peekLast = deque.peekLast();System.out.println(peekLast); // 輸出 1System.out.println(deque); // 輸出 [1]}
}

我們創建了一個 ArrayDeque 對象,并使用 addFirst() addLast() 方法在雙端隊列的開頭和末尾插入元素。然后使用 removeFirst() removeLast() 方法移除元素。使用 peekFirst()peekLast() 方法獲取元素但不移除。最后輸出雙端隊列的內容。

BlockingDeque

他是Java集合中的一個接口,是Deque的子接口,表示一個支持阻塞操作的雙向隊列。BlockingDeque 繼承了 Deque 接口的所有方法,并添加了一些阻塞方法,這些方法在隊列滿或空時會阻塞線程,直到隊列可用或有元素可用時才會繼續執行。
在這里插入圖片描述

  • putFirst(E e):將指定元素插入到雙端隊列的開頭,如果隊列已滿,則阻塞當前線程直到隊列可用。
  • putLast(E e):將指定元素插入到雙端隊列的末尾,如果隊列已滿,則阻塞當前線程直到隊列可用。
  • takeFirst():移除并返回雙端隊列的第一個元素,如果隊列為空,則阻塞當前線程直到有元素可用。
  • takeLast():移除并返回雙端隊列的最后一個元素,如果隊列為空,則阻塞當前線程直到有元素可。
  • offerFirst(E e, long timeout, TimeUnit unit):將指定元素插入到雙端隊列的開頭,如果隊列已滿,則阻塞當前線程一段時間,直到超時或隊列可用。
  • offerLast(E e, long timeout, TimeUnit unit):將指定元素插入到雙端隊列的末尾,如果隊列已滿,則阻塞當前線程一段時間,直到超時或隊列可用。
  • pollFirst(long timeout, TimeUnit unit):移除并返回雙端隊列的第一個元素,如果隊列為空,則阻塞當前線程一段時間,直到超時或有元素可用。
  • pollLast(long timeout, TimeUnit unit):移除并返回雙端隊列的最后一個元素,如果隊列為空,則阻塞當前線程一段時間,直到超時或有元素可用。

其他方法:
在這里插入圖片描述

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;public class Main {public static void main(String[] args) {BlockingDeque<Integer> blockingDeque = new LinkedBlockingDeque<>(2);try {blockingDeque.putFirst(1);blockingDeque.putLast(2);System.out.println(blockingDeque); // 輸出 [1, 2]blockingDeque.putFirst(3); // 阻塞當前線程,直到隊列可用blockingDeque.putLast(4); // 阻塞當前線程,直到隊列可用} catch (InterruptedException e) {e.printStackTrace();}}
}

創建了一個容量為 2 的 LinkedBlockingDeque 對象,并使用 putFirst() 和 putLast() 方法向雙端隊列中插入元素。當隊列已滿時,putFirst() 和 putLast() 方法會阻塞當前線程,直到隊列可用。

由于我們的隊列容量為 2,并且已經插入了兩個元素,所以在插入第三個和第四個元素時,當前線程會被阻塞,直到隊列中有空間可用。

LinkedBlockingDeque

LinkedBlockingDeque是Java中的一個雙向鏈表阻塞隊列,它實現了BlockingQueue接口,可以用于實現生產者-消費者模式等多線程場景。在本篇博客中,我將詳細介紹LinkedBlockingDeque的特性、用法以及示例代碼。

在這里插入圖片描述

LinkedBlockingDeque的常用方法

  • add(E e):將指定元素添加到隊列的尾部,如果隊列已滿,則拋出IllegalStateException異常。
  • offer(E e):將指定元素添加到隊列的尾部,如果隊列已滿,則返回false。
  • put(E e):將指定元素添加到隊列的尾部,如果隊列已滿,則阻塞直到隊列有空間可用。
  • offerFirst(E e):將指定元素添加到隊列的頭部,如果隊列已滿,則返回false。
  • offerLast(E e):將指定元素添加到隊列的尾部,如果隊列已滿,則返回false。
  • poll():獲取并移除隊列頭部的元素,如果隊列為空,則返回null。
  • poll(long timeout, TimeUnit unit):在指定的時間內等待,獲取并移除隊列頭部的元素,如果超時仍未有元素可用,則返回null。
  • take():獲取并移除隊列頭部的元素,如果隊列為空,則阻塞直到隊列非空。
  • pollFirst():獲取并移除隊列頭部的元素,如果隊列為空,則返回null。
  • pollLast():獲取并移除隊列尾部的元素,如果隊列為空,則返回null。
  • peek():獲取但不移除隊列頭部的元素,如果隊列為空,則返回null。
  • peekFirst():獲取但不移除隊列頭部的元素,如果隊列為空,則返回null。
  • peekLast():獲取但不移除隊列尾部的元素,如果隊列為空,則返回null。
  • remove(Object o):從隊列中移除指定元素,如果存在該元素則返回true,否則返回false。
  • contains(Object o):判斷隊列是否包含指定元素,如果包含則返回true,否則返回false。

其他方法:
在這里插入圖片描述

LinkedBlockingDeque的特性

  • 雙向鏈表結構:LinkedBlockingDeque內部采用雙向鏈表實現,可以高效地支持在隊列兩端的插入和刪除操作。
  • 阻塞操作:當隊列為空時,從隊列中獲取元素的操作會被阻塞,直到隊列中有元素可用;當隊列已滿時,向隊列中添加元素的操作也會被阻塞,直到隊列有空間可用。
  • 無界隊列:LinkedBlockingDeque在構造時可以選擇是否設置隊列的容量限制,如果不設置容量限制,則隊列大小理論上可以無限增長。

LinkedBlockingDeque的使用

  1. 創建LinkedBlockingDeque對象
LinkedBlockingDeque<String> deque = new LinkedBlockingDeque<>();
  1. 添加元素到隊列
deque.add("Element 1"); // 添加元素到隊列尾部
deque.offerFirst("Element 2"); // 添加元素到隊列頭部
  1. 獲取并移除隊列元素
String element = deque.poll(); // 獲取并移除隊列頭部元素
String lastElement = deque.pollLast(); // 獲取并移除隊列尾部元素
  1. 獲取但不移除隊列元素
String peekElement = deque.peek(); // 獲取但不移除隊列頭部元素
String peekLastElement = deque.peekLast(); // 獲取但不移除隊列尾部元素
  1. 阻塞操作
String element = deque.take(); // 阻塞直到隊列非空,然后獲取并移除隊列頭部元素
deque.put("Element 3"); // 阻塞直到隊列有空間可用,然后添加元素到隊列尾部

示例代碼

下面是一個簡單的生產者-消費者示例,使用LinkedBlockingDeque作為共享隊列:

import java.util.concurrent.LinkedBlockingDeque;public class ProducerConsumerExample {private static LinkedBlockingDeque<Integer> queue = new LinkedBlockingDeque<>();public static void main(String[] args) {Thread producer = new Thread(() -> {try {for (int i = 0; i < 10; i++) {queue.put(i);System.out.println("Produced: " + i);Thread.sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();}});Thread consumer = new Thread(() -> {try {for (int i = 0; i < 10; i++) {int num = queue.take();System.out.println("Consumed: " + num);}} catch (InterruptedException e) {e.printStackTrace();}});producer.start();consumer.start();}
}

LinkedBlockingDeque是一個功能強大的雙向鏈表阻塞隊列,適用于多線程生產者-消費者模式等場景。通過阻塞操作和雙向鏈表結構,它能夠高效地支持并發操作。在實際應用中,可以根據具體需求選擇合適的隊列實現來提升系統性能和可靠性。

ArrayDeque

ArrayDeque的特性

在這里插入圖片描述

  • 數組實現:ArrayDeque內部使用數組來存儲元素,可以高效地支持在隊列兩端的插入和刪除操作。
  • 雙端隊列:ArrayDeque既可以作為隊列使用,也可以作為棧使用。它支持在隊列的頭部和尾部進行元素的插入和刪除,因此可以靈活地滿足不同的需求。
  • 無界隊列:ArrayDeque在構造時不需要指定容量大小,它的大小會根據實際元素的數量自動調整,理論上可以無限增長。
  • 非線程安全:ArrayDeque不是線程安全的,如果需要在多線程環境下使用,需要進行適當的同步處理。

注意

  • 非線程安全:ArrayDeque不是線程安全的,如果需要在多線程環境下使用,需要進行適當的同步處理。可以使用Collections.synchronizedDeque()方法創建一個線程安全的ArrayDeque。

  • 不支持null元素:ArrayDeque不支持存儲null元素,如果嘗試添加null元素,會拋出NullPointerException異常。

  • 避免頻繁調整容量:ArrayDeque的內部實現是通過循環數組來存儲元素,當隊列的容量不足時,會自動進行擴容。在頻繁添加或刪除元素的場景下,可能會導致多次擴容,影響性能。如果事先能夠大致估計隊列的大小,可以通過構造函數ArrayDeque(int numElements)來指定初始容量,避免頻繁的容量調整。

  • 適用于頻繁操作兩端的場景:ArrayDeque的優勢在于支持高效地在隊列的兩端進行插入和刪除操作。如果只需要在隊列的一端進行操作,建議使用LinkedList或ArrayBlockingQueue等其他隊列實現。

  • 注意棧操作的順序:如果將ArrayDeque用作棧使用,需要注意棧操作的順序。使用push()方法將元素添加到棧頂,使用pop()方法移除并返回棧頂元素。棧操作需要保持一致的順序,否則可能導致元素順序的混亂。

  • 避免過度依賴索引操作:由于ArrayDeque是基于數組實現的,它支持通過索引來訪問元素。但是,在頻繁插入和刪除元素的場景下,使用索引操作可能會導致性能下降。因此,在使用ArrayDeque時,應盡量避免過度依賴索引操作,而是使用隊列提供的方法來操作元素。

在這里插入圖片描述

ArrayDeque的使用

  1. 創建ArrayDeque對象
ArrayDeque<String> deque = new ArrayDeque<>();
  1. 添加元素到隊列
deque.add("Element 1"); // 添加元素到隊列尾部
deque.offerFirst("Element 2"); // 添加元素到隊列頭部
  1. 獲取并移除隊列元素
String element = deque.poll(); // 獲取并移除隊列頭部元素
String lastElement = deque.pollLast(); // 獲取并移除隊列尾部元素
  1. 獲取但不移除隊列元素
String peekElement = deque.peek(); // 獲取但不移除隊列頭部元素
String peekLastElement = deque.peekLast(); // 獲取但不移除隊列尾部元素
  1. 棧操作
deque.push("Element 3"); // 將元素添加到棧頂
String popElement = deque.pop(); // 移除并返回棧頂元素

示例代碼

import java.util.ArrayDeque;public class ArrayDequeExample {public static void main(String[] args) {ArrayDeque<String> queue = new ArrayDeque<>();queue.offer("Element 1");queue.offer("Element 2");System.out.println(queue.poll()); // 輸出: Element 1ArrayDeque<String> stack = new ArrayDeque<>();stack.push("Element 3");stack.push("Element 4");System.out.println(stack.pop()); // 輸出: Element 4}
}

ArrayDeque是一個非常實用的雙端隊列,可以靈活地支持隊列和棧的操作。通過數組實現和雙端插入和刪除操作,它能夠高效地滿足不同場景下的需求。在實際應用中,可以根據具體需求選擇合適的隊列實現來提升系統性能和可靠性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/711640.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/711640.shtml
英文地址,請注明出處:http://en.pswp.cn/news/711640.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

docker搭建git服務器

1、docker搭建git服務器 總體思路&#xff1a;服務端通過docker搭建git服務器&#xff0c;客戶端創建git的賬戶及公鑰密鑰&#xff1b; 1&#xff09;服務端# 創建容器 # --privileged 獲得完整的root權限 # /usr/sbin/init 啟動容器執行的第一個命令 以便可以使用systemctl命…

2024年FPGA可以進嗎

2024年&#xff0c;IC設計FPGA行業仍有可能是一個極具吸引力和活力的行業&#xff0c;主要原因包括&#xff1a; 1. 技術發展趨勢&#xff1a;隨著5G、人工智能、物聯網、自動駕駛、云計算等高新技術的快速發展和廣泛應用&#xff0c;對集成電路尤其是高性能、低功耗、定制化芯…

【UE 材質】制作加載圖案(2)

在上一篇&#xff08;【UE 材質】制作加載圖案&#xff09;基礎上繼續實現如下效果的加載圖案 效果 步驟 1. 復制一份上一篇制作的材質并打開 2. 添加“Floor”節點向下取整 除相同的平鋪數 此時的效果如下 刪除如下節點 通過“Ceil”向上取整&#xff0c;參數“Tiling”默認…

教師招聘和事業編d類有什么區別嗎

每年都有大批懷揣教育夢想的年輕人&#xff0c;站在職業的十字路口&#xff0c;對未來充滿期許與疑惑。他們中的許多人都會面臨這樣一個問題&#xff1a;教師招聘和事業編D類&#xff0c;到底有什么區別&#xff1f;今天&#xff0c;就讓我來為你揭開這兩者的神秘面紗。 別被這…

【大數據】Flink SQL 語法篇(五):Regular Join、Interval Join

《Flink SQL 語法篇》系列&#xff0c;共包含以下 10 篇文章&#xff1a; Flink SQL 語法篇&#xff08;一&#xff09;&#xff1a;CREATEFlink SQL 語法篇&#xff08;二&#xff09;&#xff1a;WITH、SELECT & WHERE、SELECT DISTINCTFlink SQL 語法篇&#xff08;三&…

ubuntu系統下大數據服務器磁盤調優測試記錄

一、背景 在kvm虛擬機ubuntu操作系統大數據平臺測試的過程中&#xff0c;遭遇了磁盤I/O性能的瓶頸&#xff0c;因有cpu綁核操作&#xff0c;故有做隔核操作驗證是否是綁核影響的磁盤I/O&#xff0c;后又對磁盤進行透傳以及掛內存盤等操作&#xff1b; 二、磁盤介紹 2.1 磁盤…

『NLP學習筆記』圖解 BERT、ELMo和GPT(NLP如何破解遷移學習)

圖解 BERT、ELMo和GPT(NLP如何破解遷移學習) 文章目錄 一. 前言二. 示例-句子分類三. 模型架構3.1. 模型輸入3.2. 模型輸出四. BERT VS卷積神經網絡五. 詞嵌入新時代5.1. 簡要回顧詞嵌入Word Embedding5.2. ELMo: 上下文語境很重要5.2.1. ELMo的秘密是什么?5.3. ULM-FiT:將遷…

藍橋杯Python B組練習——斐波那契數列

一、題目 定義 斐波那契數列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又稱黃金分割數列&#xff0c;因數學家萊昂納多斐波那契&#xff08;Leonardo Fibonacci&#xff09;以兔子繁殖為例子而引入&#xff0c;故又稱為“兔子數列”&#xff0c;指的是這樣一個數…

Linux x86平臺獲取sys_call_table

文章目錄 前言一、根據call *sys_call_table來獲取二、使用dump_stack三、根據MSR_LSTAR寄存器四、使用sys_close參考資料 前言 Linux 3.10.0 – x86_64 最簡單獲取sys_call_table符號的方法&#xff1a; # cat /proc/kallsyms | grep sys_call_table ffffffff816beee0 R sy…

隨想錄算法訓練營第四十七天|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

198.打家劫舍 public class Solution {public int Rob(int[] nums) {if(nums.Length0){return 0;}if(nums.Length1){return nums[0];}int[] dpnew int[nums.Length1];dp[0]nums[0];dp[1]Math.Max(nums[0],nums[1]);for(int i2;i<nums.Length;i){dp[i]Math.Max(dp[i-2]nums[…

什么是 HTTPS 證書?作用是什么?

HTTPS 證書&#xff0c;即超文本傳輸安全協議證書&#xff08;Hypertext Transfer Protocol Secure&#xff09;&#xff0c;是網站安全的關鍵組成部分。它通過 SSL/TLS 加密協議&#xff0c;確保用戶與網站之間的數據傳輸是加密和安全的。 什么是 HTTPS 證書&#xff1f; HT…

使用Docker -compose啟動自定義jar包

步驟1&#xff1a;編寫docker-compose.yml文件 首先我們需要編寫一個docker-compose.yml文件來定義我們的服務傳到我們的云服務器上 以下是一個示例&#xff1a; version: 3 services:app:build:context: .dockerfile: Dockerfileports:- 8080:8080volumes:- ./app.jar:/app…

可視化圖表:水球圖,展示百分比的神器。

Hi&#xff0c;我是貝格前端工場的老司機&#xff0c;本文分享可視化圖表設計的水球圖設計&#xff0c;歡迎老鐵持續關注我們。 一、水球圖及其作用 水球圖是一種特殊的可視化圖表&#xff0c;它主要用于展示百分比或比例的數據&#xff0c;并以水球的形式進行呈現。水球圖的作…

2023面試題

目錄 題目 1:JVM 整體結構是什么樣的? 8 題目 3:Object 類有哪些方法? 11 題目 4:靜態變量與實例變量區別? 11 題目 5:String 類的常用方法有哪些? 11 題目 6:數組有沒有 length()方法?String 有沒有 length() 12 題目 7:String、StringBuffer、StringBuilder 的區別…

【k8s 訪問控制--認證與鑒權】

1、身份認證與權限 前面我們在操作k8s的所有請求都是通過https的方式進行請求&#xff0c;通過REST協議操作我們的k8s接口&#xff0c;所以在k8s中有一套認證和鑒權的資源。 Kubenetes中提供了良好的多租戶認證管理機制&#xff0c;如RBAC、ServiceAccount還有各種策路等。通…

集合篇之ArrayList

一、源碼如何分析&#xff1f; 1.成員變量 2.構造方法 3.關鍵方法 一些添加的方法。 二、debug看源碼 我們給出下面代碼&#xff1a; public void test01() {ArrayList<Integer> list new ArrayList<>();list.add(1);for (int i 2; i < 10; i) {list.add(i…

H5:段落標簽與換行標簽

目錄 一.前言 二.正文 1.段落標簽 2.換行標簽 三.結語 一.前言 學習前端&#xff0c;從此起飛&#xff0c;愿你堅持&#xff0c;直至等頂。 二.正文 1.段落標簽 <p></p> p為段落標簽&#xff0c;由英文paragraph簡寫而來&#xff0c;用于將一段某一部分文本&am…

算法練習第九天|232.用棧實現隊列、225. 用隊列實現棧

熟悉棧和隊列的方法&#xff1b;熟悉棧和隊列的數據結構&#xff0c;不涉及算法 232.用棧實現隊列 import java.util.Stack; class MyQueue {//負責進棧的Stack<Integer> stackIn;//負責出棧的Stack<Integer> stackOut;public MyQueue() {stackIn new Stack<&…

Rocketmq 入門介紹

從零手寫實現 mq 詳細介紹一下 rocketmq RocketMQ 是由阿里巴巴開發的分布式消息隊列系統&#xff0c;它是一個低延遲、高可靠、高吞吐量的消息中間件。 RocketMQ 最初是作為阿里巴巴的內部項目進行開發的&#xff0c;后來成為了 Apache 軟件基金會下的頂級項目&#xff0c;以…

精讀《React 高階組件》

本期精讀文章是&#xff1a;React Higher Order Components in depth 1 引言 高階組件&#xff08; higher-order component &#xff0c;HOC &#xff09;是 React 中復用組件邏輯的一種進階技巧。它本身并不是 React 的 API&#xff0c;而是一種 React 組件的設計理念&…