Queue 和 Deque

ℹ️定位说明

本篇是 Queue 系列总览:Queue(FIFO)/ Deque(双端)两接口 + 三实现速览。深读动线:ArrayDeque(栈与双端首选)→ PriorityQueue(堆与 Top K)。LinkedList 的队列角色见 List 系列篇内"扩展用法"。

Java 中的 QueueDeque 是处理队列、双端队列和栈操作的重要接口。QueuePriorityQueue 提供基于优先级的出队操作,底层是最小堆;而 Deque 支持从两端插入和删除,ArrayDeque 是其高性能实现,适用于栈和双端队列场景。LinkedList 同时实现了 ListDeque 接口,但性能不如专用实现。它们都不是线程安全的,适用于单线程或通过同步手段控制并发。

Queue 接口的两套方法(高频面试点)

同一个动作,Queue 都提供两种风格:失败抛异常 vs 失败返回特殊值——面试和源码里来回出现,必须分清:

动作 抛异常版 返回特殊值版 失败时的表现
入队 add(e) offer(e) 容量受限队列满时:抛 IllegalStateException / 返回 false
出队 remove() poll() 队空时:抛 NoSuchElementException / 返回 null
看队头(不出队) element() peek() 队空时:抛 NoSuchElementException / 返回 null

记忆法:e 开头三兄弟(add/remove/element)脾气硬会抛异常;o/p 开头三兄弟(offer/poll/peek)温和返回 null/false。日常写代码推荐 offer/poll/peek——用返回值判空比捕获异常自然得多。Deque 把这套矩阵在头尾各复制一份(addFirst/offerFirstremoveLast/pollLast……),规则相同。

ArrayDeque —— 高性能双端队列

  • 底层结构:循环数组(动态扩容)
  • 支持操作:头尾插入、删除、队列 & 栈行为
  • 优势
    • LinkedList 更高效
    • 不允许存 null 元素(避免歧义)
    • 不线程安全(多线程环境需加锁)
  • 适合场景:栈、队列、双端队列、缓存队列等

示例用法:

Deque<String> deque = new ArrayDeque<>();
deque.offerFirst("A"); // 头部插入
deque.offerLast("B");  // 尾部插入
deque.pollFirst();     // 头部弹出
deque.pollLast();      // 尾部弹出

类比 C++:std::deque(双端队列)

PriorityQueue —— 优先级队列(最小堆)

  • 底层结构:基于 最小堆 的数组实现
  • 排序规则:默认按元素的自然顺序(或传入 Comparator)
  • 元素特点:允许重复,不允许 null
  • 应用场景:定时任务调度、最短路径、Top K 问题等

示例用法:

PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.offer(5);
pq.offer(2);
pq.offer(8);
System.out.println(pq.poll()); // 输出 2(最小值)

类比 C++:std::priority_queue(但 Java 默认是最小堆,C++ 是最大堆)

LinkedList —— 多面手(同时是 List + Queue + Deque)

  • 既实现了 List 接口,又实现了 Deque 接口
  • 适合需要频繁头尾插入删除的双端队列
  • 但性能略逊于 ArrayDeque,主要用于兼容性和老代码场景
特性 Queue Deque
接口定义 FIFO 队列 双端队列(可模拟栈)
代表实现类 LinkedList, PriorityQueue LinkedList, ArrayDeque
支持方向 只能尾进头出 头尾都可进出(更灵活)
推荐使用 消息队列、调度器 栈、缓存、滑动窗口等
是否线程安全 ❌(需加锁) ❌(需加锁)
⚠️用栈时用 `Deque`,别用 `Stack` 类

Java 自带的 java.util.Stack 继承自 Vector(见 List 系列 03 篇),继承了方法级 synchronized 的粗粒度锁,且官方 Javadoc 自己都建议不再使用。新代码写栈统一用 Deque<Integer> stack = new ArrayDeque<>();push()/pop()/peek()——方法名一样,性能好得多。与阻塞队列(BlockingQueue 家族)相关的并发话题,等 03-Java并发分区再展开。

--- ⬅️ TreeSet源码分析 🏠 00-Java ➡️ ArrayDeque