当前位置:首页 > 文章列表 > 文章 > java教程 > Java ArrayDeque 怎样实现双端队列的首尾操作

Java ArrayDeque 怎样实现双端队列的首尾操作

来源:17golang原创 2026-10-20 00:45:27 0浏览 收藏

我第一次把双端队列接进任务调度代码时,真正容易写错的不是 new ArrayDeque(),而是“这一端到底是谁”和“空了以后要异常还是要特殊值”。先给结论:ArrayDeque 用 first 表示头部、last 表示尾部;需要明确失败就用 add/remove/element 这一组,需要把空队列当成普通分支就用 offer/poll/peek。它不允许存入 null,也不是线程安全容器。

官方地址:https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/ArrayDeque.html

下面的示例只讨论首尾操作和边界,不把 ArrayDeque 包装成共享并发队列,也不把静态说明图当成运行截图。

先把 first 和 last 分清楚

ArrayDeque 是 Deque 的可扩容数组实现。对一个普通队列,可以把头部理解为下一次取出的方向,把尾部理解为新元素通常追加的方向;对双端队列,两边都能插入、删除和查看。我的经验是先在变量旁写清“头部/尾部”,再选方法名,避免只凭 add 和 remove 猜方向。

ArrayDeque 与 Deque 以及 first 头部和 last 尾部 API 的静态结构说明图
图1:结构说明图,展示容器、头部、尾部与首尾方法的静态对应关系;不是运行截图。

需要从头部放入元素时,用 addFirst(e);从尾部放入时,用 addLast(e)。删除对应使用 removeFirst() 和 removeLast(),只查看而不删除则使用 peekFirst() 和 peekLast()。这些名字比把队列当作一条没有方向的容器更适合维护。

插入、删除、查看:先决定失败语义

Queue 和 Deque 的一组方法有意分成两种风格:一组失败时抛异常,另一组返回特殊值。ArrayDeque 没有固定容量限制,所以插入通常不会因为“满了”而失败,但方法成对语义仍然值得保留。

目的明确失败普通分支
插入头部addFirstofferFirst
删除头部removeFirstpollFirst
查看头部getFirstpeekFirst
队列尾部addoffer
删除队头removepoll
查看队头elementpeek

例如,空队列可能是业务允许的“没有待处理任务”,就可以用 poll() 或 peek() 让调用方判断 null。如果空队列说明程序状态已经不对,remove() 或 element() 抛出的 NoSuchElementException 会更早暴露问题。

ArrayDeque 中异常版、特殊值版和栈式别名 API 的静态关系说明图
图2:关系说明图,比较异常版、特殊值版和栈式别名的边界;不是运行结果截图。

用代码把首尾选择写出来

下面把两个常见意图放在一起:任务队列从尾部加入、从头部取出;撤销栈则只使用头部。注释只解释关键语义,避免把每一行都写成注释。

import java.util.ArrayDeque;

public class ArrayDequeEnds {
    public static void main(String[] args) {
        var tasks = new ArrayDeque();
        // 尾部追加新任务,头部取出最早进入的任务
        tasks.addLast("编译");
        tasks.addLast("打包");
        String next = tasks.pollFirst();
        System.out.println(next); // 预期示例输出:编译

        var undo = new ArrayDeque();
        // push 等价于 addFirst,适合把同一端当作栈顶
        undo.push("改配置");
        undo.push("改代码");
        String latest = undo.pop();
        System.out.println(latest); // 预期示例输出:改代码

        // peek 只查看,不删除;空队列时返回 null
        String waiting = tasks.peekFirst();
        if (waiting == null) {
            System.out.println("没有待处理任务");
        }
    }
}

push(e) 是把元素放到头部的栈式表达,pop() 则从头部删除并返回。若读者看到的是“撤销最近一次操作”,push/pop 比 addFirst/removeFirst 更能表达意图;若读者看到的是“双端数据结构”,首尾方法名更直接。

空队列、null 和共享访问要单独处理

ArrayDeque 禁止 null 元素,这反而让 poll、peek 返回 null 时具有明确含义:队列为空,而不是取出了一个合法的 null。不要为了绕过判断把 null 当作占位元素塞进去。

另外,ArrayDeque 没有内部同步。单线程任务循环、局部的请求处理和明确由一个所有者管理的工作队列都可以考虑它;多个线程同时修改同一个实例时,不能仅因为类型名里有 Queue 就认为它提供并发安全。需要跨线程传递任务时,应另行选择并发队列或在外部建立同步边界。

我会在代码评审里检查三件事:调用方是否已经决定空队列是异常还是分支;方法名是否和数据方向一致;容器是否被多个线程共享。三项都清楚,ArrayDeque 的 API 基本不会再靠记忆猜。

相关问题

  • ArrayDeque 的 add 和 offer 怎么选? 两者都表示插入;当失败应作为异常暴露时用 add,需要用返回值表达插入失败时用 offer。
  • poll 和 remove 的区别是什么? 两者都会删除并返回队头;空队列时 poll 返回 null,remove 抛出 NoSuchElementException。
  • ArrayDeque 能不能存 null? 不能。空队列返回 null 的约定也依赖这个限制。
  • push 和 addFirst 有什么关系? push 是栈语义的头部插入别名;选择它还是 addFirst,取决于你想表达栈还是双端队列。
版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Java 虚拟线程怎样为 ThreadLocal 上下文设置继承边界Java 虚拟线程怎样为 ThreadLocal 上下文设置继承边界
上一篇
Java 虚拟线程怎样为 ThreadLocal 上下文设置继承边界
Java jcmd 怎样导出虚拟线程线程栈
下一篇
Java jcmd 怎样导出虚拟线程线程栈
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    551次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    603次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    629次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    583次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    408次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码