Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

    • Java集合概述
    • ArrayList
    • LinkedList
    • HashMap
    • LinkedHashMap
    • HashSet
    • TreeMap
    • Queue&Deque
      • 1. Queue 是什么
      • 2. Queue 方法分组
      • 3. Deque 是什么
      • 4. Deque 方法
      • 5. ArrayDeque
      • 6. LinkedList 作为队列
      • 7. PriorityQueue
      • 8. PriorityQueue 注意点
      • 9. 阻塞队列
      • 10. Queue 选型
      • 11. 常见算法场景
        • 11.1 BFS
        • 11.2 单调队列
        • 11.3 Top K
      • Tips 快问快答
    • 迭代器与遍历机制
    • Collections工具类
    • 集合排序与比较器
    • 集合选型与常见问题
  • Java并发

  • Java IO

  • JVM

  • Java
  • Java集合
Wray
2026-06-24
目录

Queue&Deque

Queue 和 Deque 是 Java 集合框架中用于表达“排队”和“两端操作”的接口。它们不仅能表示普通队列,还能表示双端队列、栈、优先级队列,以及并发中的阻塞队列。

如果 List 强调按位置访问,Queue/Deque 强调的是元素进出的规则。

# 1. Queue 是什么

Queue 通常表示先进先出,简称 FIFO。

入队 offer
   │
   ▼
tail [C, B, A] head
              │
              ▼
           poll 出队

示例:

Queue<String> queue = new ArrayDeque<>();
queue.offer("A");
queue.offer("B");

System.out.println(queue.poll()); // A
System.out.println(queue.poll()); // B

# 2. Queue 方法分组

Queue 方法有两套风格:失败时抛异常,或返回特殊值。

操作 抛异常 返回特殊值
入队 add(e) offer(e)
出队 remove() poll()
查看队首 element() peek()

推荐业务代码优先使用返回特殊值的方法:

String task = queue.poll();
if (task != null) {
    process(task);
}

空队列时:

方法 行为
remove() 抛 NoSuchElementException
poll() 返回 null
element() 抛 NoSuchElementException
peek() 返回 null

# 3. Deque 是什么

Deque 是 double-ended queue,双端队列。它支持从两端插入和删除。

offerFirst             offerLast
    │                     │
    ▼                     ▼
head [A, B, C, D] tail
    ▲                     ▲
 pollFirst             pollLast

示例:

Deque<String> deque = new ArrayDeque<>();
deque.offerFirst("B");
deque.offerFirst("A");
deque.offerLast("C");

System.out.println(deque.pollFirst()); // A
System.out.println(deque.pollLast());  // C

# 4. Deque 方法

操作 头部 尾部
插入,失败抛异常 addFirst addLast
插入,失败返回 false offerFirst offerLast
删除,失败抛异常 removeFirst removeLast
删除,失败返回 null pollFirst pollLast
查看,失败抛异常 getFirst getLast
查看,失败返回 null peekFirst peekLast

Deque 也提供栈方法:

栈操作 Deque 方法
入栈 push(e),等价于 addFirst(e)
出栈 pop(),等价于 removeFirst()
查看栈顶 peek()

# 5. ArrayDeque

ArrayDeque 是基于循环数组的双端队列。

数组:
[_, C, D, _, _, A, B, _]
       ▲           ▲
      tail        head

当头尾移动到数组边界时,会绕回数组另一端。

特点:

特点 说明
头尾操作快 均摊 O(1)
不允许 null null 用作空返回值标记
内存紧凑 比链表节点更省内存
非线程安全 多线程使用需额外同步

适合:

  • 普通队列。
  • 栈。
  • 双端队列。
  • BFS 临时队列。

示例:

Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);
stack.push(2);
System.out.println(stack.pop()); // 2

# 6. LinkedList 作为队列

LinkedList 也实现了 Deque。

Deque<String> deque = new LinkedList<>();

但它基于链表,每个元素一个节点对象,内存开销较大,缓存局部性较差。

对比:

对比项 ArrayDeque LinkedList
底层结构 循环数组 双向链表
内存占用 较低 较高
是否允许 null 不允许 允许
作为栈/队列 更推荐 一般

除非必须允许 null 或依赖链表特性,否则栈和队列优先 ArrayDeque。

# 7. PriorityQueue

PriorityQueue 是优先级队列,出队顺序不是插入顺序,而是优先级顺序。

默认小顶堆:

Queue<Integer> queue = new PriorityQueue<>();
queue.offer(3);
queue.offer(1);
queue.offer(2);

System.out.println(queue.poll()); // 1

结构:

小顶堆:
        1
      /   \
     3     2

自定义优先级:

Queue<Task> queue = new PriorityQueue<>(
        Comparator.comparingInt(Task::getPriority)
);

如果优先级越大越先出:

Queue<Task> queue = new PriorityQueue<>(
        Comparator.comparingInt(Task::getPriority).reversed()
);

# 8. PriorityQueue 注意点

注意点 说明
不保证整体有序遍历 只有每次 poll 才保证取出当前最小或最大
不允许 null 避免和空队列返回值混淆
非线程安全 并发场景用 PriorityBlockingQueue
比较器必须稳定 比较规则混乱会导致堆语义异常

错误理解:

System.out.println(priorityQueue);

打印结果不一定是排序后的列表。要按优先级取出:

while (!queue.isEmpty()) {
    System.out.println(queue.poll());
}

# 9. 阻塞队列

并发编程中常用 BlockingQueue,它不只是集合结构,还是线程协作工具。

常见实现:

实现 特点
ArrayBlockingQueue 有界数组阻塞队列
LinkedBlockingQueue 链表阻塞队列,可有界
PriorityBlockingQueue 优先级阻塞队列
DelayQueue 延迟到期后才能取出
SynchronousQueue 不存储元素,直接交接

生产消费模型:

Producer -> put -> BlockingQueue -> take -> Consumer

阻塞队列会在 Java 并发章节详细展开。

# 10. Queue 选型

需求 推荐
普通 FIFO 队列 ArrayDeque
栈 ArrayDeque
双端队列 ArrayDeque
允许 null 的双端队列 LinkedList
优先级队列 PriorityQueue
多线程生产消费 BlockingQueue
并发优先级队列 PriorityBlockingQueue

# 11. 常见算法场景

# 11.1 BFS

Queue<Node> queue = new ArrayDeque<>();
queue.offer(root);

while (!queue.isEmpty()) {
    Node node = queue.poll();
    for (Node child : node.children()) {
        queue.offer(child);
    }
}

# 11.2 单调队列

滑动窗口最大值等问题常用 Deque 保存候选元素。

窗口移动
  │
  ▼
Deque 保持从大到小
  │
  ▼
队首就是当前最大值

# 11.3 Top K

使用小顶堆维护最大的 K 个元素:

PriorityQueue<Integer> heap = new PriorityQueue<>();
for (int value : values) {
    heap.offer(value);
    if (heap.size() > k) {
        heap.poll();
    }
}

# Tips 快问快答

Q:Queue 和 Deque 最大区别是什么? A:Queue 通常只操作队尾和队首,Deque 支持两端插入和删除。

Q:为什么推荐 offer/poll/peek? A:它们失败时返回特殊值,业务代码更容易处理空队列或容量限制。

Q:栈为什么推荐 ArrayDeque 而不是 Stack? A:Stack 是老类,继承 Vector;ArrayDeque 更现代、轻量。

Q:ArrayDeque 可以放 null 吗? A:不可以,null 被用于表示某些操作的空返回值。

Q:PriorityQueue 遍历是有序的吗? A:不保证。只有连续 poll 才按优先级取出。

Q:PriorityQueue 默认大顶堆还是小顶堆? A:默认小顶堆,即自然顺序最小元素先出。

Q:队列多线程生产消费用什么? A:使用 BlockingQueue 系列。

Q:LinkedList 适合当队列吗? A:能用,但多数普通场景 ArrayDeque 更合适。

Q:Top K 常用什么集合? A:常用 PriorityQueue 维护大小为 K 的堆。

Q:BFS 常用什么队列? A:普通单线程 BFS 通常用 ArrayDeque。

上次更新: 2026/06/24, 16:37:44
TreeMap
迭代器与遍历机制

← TreeMap 迭代器与遍历机制→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式