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.mzph.cn/news/711640.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【UE 材质】制作加载图案(2)

在上一篇&#xff08;【UE 材质】制作加载图案&#xff09;基础上继续实现如下效果的加载图案 效果 步骤 1. 复制一份上一篇制作的材质并打开 2. 添加“Floor”节点向下取整 除相同的平铺数 此时的效果如下 删除如下节点 通过“Ceil”向上取整&#xff0c;参数“Tiling”默认…

教师招聘和事业编d类有什么区别吗

每年都有大批怀揣教育梦想的年轻人&#xff0c;站在职业的十字路口&#xff0c;对未来充满期许与疑惑。他们中的许多人都会面临这样一个问题&#xff1a;教师招聘和事业编D类&#xff0c;到底有什么区别&#xff1f;今天&#xff0c;就让我来为你揭开这两者的神秘面纱。 别被这…

ubuntu系统下大数据服务器磁盘调优测试记录

一、背景 在kvm虚拟机ubuntu操作系统大数据平台测试的过程中&#xff0c;遭遇了磁盘I/O性能的瓶颈&#xff0c;因有cpu绑核操作&#xff0c;故有做隔核操作验证是否是绑核影响的磁盘I/O&#xff0c;后又对磁盘进行透传以及挂内存盘等操作&#xff1b; 二、磁盘介绍 2.1 磁盘…

蓝桥杯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…

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

Hi&#xff0c;我是贝格前端工场的老司机&#xff0c;本文分享可视化图表设计的水球图设计&#xff0c;欢迎老铁持续关注我们。 一、水球图及其作用 水球图是一种特殊的可视化图表&#xff0c;它主要用于展示百分比或比例的数据&#xff0c;并以水球的形式进行呈现。水球图的作…

【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…

精读《React 高阶组件》

本期精读文章是&#xff1a;React Higher Order Components in depth 1 引言 高阶组件&#xff08; higher-order component &#xff0c;HOC &#xff09;是 React 中复用组件逻辑的一种进阶技巧。它本身并不是 React 的 API&#xff0c;而是一种 React 组件的设计理念&…

【QT+QGIS跨平台编译】之五十三:【QGIS_CORE跨平台编译】—【qgssqlstatementparser.cpp生成】

文章目录 一、Bison二、生成来源三、构建过程一、Bison GNU Bison 是一个通用的解析器生成器,它可以将注释的无上下文语法转换为使用 LALR (1) 解析表的确定性 LR 或广义 LR (GLR) 解析器。Bison 还可以生成 IELR (1) 或规范 LR (1) 解析表。一旦您熟练使用 Bison,您可以使用…

2024年个人护理赛道选品风向在哪?这份赛盈分销选品攻略必看!

2024年还会卷下去吗&#xff1f;看到一位行业大佬分享的内容深有感触&#xff1a;坚定做好产品&#xff0c;不做大卖&#xff0c;就不存在卷不卷。 有人出局&#xff0c;也会有人入局&#xff0c;并且深耕领域做大做强。 专注口腔护理的Bitvae入行不到两年&#xff0c;凭借一款…

C#学习(十四)——垃圾回收、析构与IDisposable

一、何为GC 数据是存储在内存中的&#xff0c;而内存又分为Stack栈内存和Heap堆内存 Stack栈内存Heap堆内存速度快、效率高结构复杂类型、大小有限制对象只能保存简单的数据引用数据类型基础数据类型、值类型- 举个例子 var c new Customer{id: 123,name: "Jack"…

微信小程序手势冲突?不存在的!

原生的应用经常会有页面嵌套列表&#xff0c;滚动列表能够改变列表大小&#xff0c;然后还能支持列表内下拉刷新等功能。看了很多的小程序好像都没有这个功能&#xff0c;难道这个算是原生独享的吗&#xff0c;难道是由于手势冲突无法实现吗&#xff0c;冷静的思考了一下&#…

【InternLM 实战营笔记】XTuner 大模型单卡低成本微调实战

XTuner概述 一个大语言模型微调工具箱。由 MMRazor 和 MMDeploy 联合开发。 支持的开源LLM (2023.11.01) InternLM Llama&#xff0c;Llama2 ChatGLM2&#xff0c;ChatGLM3 Qwen Baichuan&#xff0c;Baichuan2 Zephyr 特色 傻瓜化&#xff1a; 以 配置文件 的形式封装了大…

看待事物的层与次 | DBA与架构的一次对话交流

前言 在计算机软件业生涯中,想必行内人或多或少都能感受到系统架构设计与数据库系统工程的重要性,也能够清晰地认识到在计算机软件行业中技术工程师这个职业所需要的专业素养和必备技能! 背景 通过自研的数据库监控管理工具,发现 SQL Server 数据库连接数在1-2K之间,想…

Yii2中如何使用scenario场景,使rules按不同运用进行字段验证

Yii2中如何使用scenario场景&#xff0c;使rules按不同运用进行字段验证 当创建news新闻form表单时&#xff1a; 添加新闻的时候执行create动作。 必填字段&#xff1a;title-标题&#xff0c;picture-图片&#xff0c;description-描述。 这时候在model里News.php下rules规则…

利用coze 搭建“全功能“微信客服(2)

紧跟上篇 利用coze 搭建"全功能"微信客服&#xff08;1&#xff09;&#xff0c;不知道来龙去脉自行查阅 先表扬下coze: coze 是国内少数开放平台之一&#xff0c;里面提供各种插件还可以开发工作流&#xff0c;让你可以实现多模态全功能大模型 吐槽 没有API开放接口…

2024亚马逊全球开店注册前需要准备什么?

在2023年出海四小龙SHEIN、Temu、速卖通AliExpress、TikTok Shop快速增长扩张&#xff0c;成为了中国跨境卖家“逃离亚马逊”的新选择。但是&#xff0c;跨境电商看亚马逊。当前&#xff0c;亚马逊仍然是跨境电商行业的绝对老大&#xff0c;占有将近70%成以上的业务份额。 作为…

分享fastapi低级错误

我是创建表的时候把__tablename__ 写成__table__然后一直报这个错误

端游如何防破解

在2023年这个游戏大年中&#xff0c;诸多热门大作涌现&#xff0c;作为世界级IP哈利哈利波特的衍生游戏——《霍格沃茨之遗》毫无悬念地成为2023年游戏圈的首款爆款作品&#xff0c;斩获了一众玩家的青睐。 在众多光环的加持下&#xff0c;《霍格沃茨之遗》很快被著名游戏破解…