一、核心概念与继承体系

二、Queue 核心方法与实现
1. 核心操作:
方法 | 说明 | 异常处理 |
---|---|---|
offer(e) |
添加元素(推荐) | 失败返回false |
add(e) |
添加元素 | 失败抛IllegalStateException |
poll() |
移除并返回队头元素 | 空队列返回null |
remove() |
移除并返回队头元素 | 空队列抛NoSuchElementException |
peek() |
查看队头元素(不删除) | 空队列返回null |
element() |
查看队头元素(不删除) | 空队列抛NoSuchElementException |
2. 常用实现类:
-
LinkedList:基于链表,支持null元素
-
PriorityQueue:基于堆的优先级队列(自然序/Comparator)
-
ArrayBlockingQueue:固定大小的阻塞队列(线程安全)
-
LinkedBlockingQueue:可选有界阻塞队列(线程安全)
三、Deque 双端队列扩展
1. 核心操作增强:
java
// 头部操作
offerFirst(e) // 头部插入
pollFirst() // 头部移除
peekFirst() // 查看头部
// 尾部操作
offerLast(e) // 尾部插入(等价于offer)
pollLast() // 尾部移除
peekLast() // 查看尾部
// 栈操作
push(e) // = offerFirst(e)
pop() // = removeFirst()
2. 作为队列使用(FIFO)的API:
java
// 队列操作(FIFO:先进先出)
offerLast(e) 或 offer(e) // 入队(尾部添加)
pollFirst() 或 poll() // 出队(头部移除)
peekFirst() 或 peek() // 查看队头
3. 作为栈使用(LIFO)的API:
java
// 栈操作(LIFO:后进先出)
push(e) // 入栈 = addFirst(e)
pop() // 出栈 = removeFirst()
peekFirst() // 查看栈顶
4. API使用对照表:
操作 | 队列模式(FIFO) | 栈模式(LIFO) | 等效方法 |
---|---|---|---|
添加元素 | offerLast(e) / offer(e) |
push(e) |
addFirst(e) (栈) |
addLast(e) (队列) |
|||
移除元素 | pollFirst() / poll() |
pop() |
removeFirst() |
查看元素 | peekFirst() / peek() |
peekFirst() |
getFirst() |
5. 代码示例:
java
Deque<String> deque = new ArrayDeque<>();
// 作为队列使用(FIFO)
deque.offerLast("A"); // 队尾添加
deque.offerLast("B");
System.out.println(deque.pollFirst()); // A(队头移除)
// 作为栈使用(LIFO)
deque.push("C"); // 入栈
deque.push("D");
System.out.println(deque.pop()); // D(出栈)
// 混合操作(不推荐但可能)
deque.offerLast("E"); // 队尾添加(队列操作)
deque.push("F"); // 栈顶添加(栈操作)
System.out.println(deque.pollFirst()); // F(混合操作结果)
6. 常用实现类:
-
ArrayDeque:基于循环数组(默认容量16,性能最优)
-
LinkedList:基于双向链表(支持索引访问)
-
LinkedBlockingDeque:线程安全阻塞双端队列
四、与其他集合类对比
特性 | Queue/Deque | List | Set | Map |
---|---|---|---|---|
数据结构 | 线性序列 | 线性序列 | 哈希表/树 | 键值对 |
元素顺序 | FIFO/LIFO/优先级 | 插入顺序/索引 | 无序/排序 | 无序/键排序 |
重复元素 | 允许 | 允许 | 不允许 | 值允许,键不允许 |
空值支持 | 部分实现支持 | 允许 | HashSet允许 | HashMap允许值 |
访问方式 | 端点访问 | 索引/迭代器 | 迭代器 | 键访问 |
典型实现 | ArrayDeque, PriorityQueue | ArrayList, LinkedList | HashSet, TreeSet | HashMap, TreeMap |
五、使用场景与最佳实践
1. 队列场景:
-
任务调度:
ThreadPoolExecutor
使用BlockingQueue
-
消息传递:生产者-消费者模式
-
广度优先搜索(BFS)
2. 双端队列场景:
-
撤销操作栈:
ArrayDeque
替代Stack
-
滑动窗口算法
-
工作窃取算法(Work Stealing)
3. 选择指南:

六、常见问题
Q1:Queue和Deque的主要区别是什么?
A:
功能定位:
Queue
是标准FIFO队列(尾部添加,头部移除)
Deque
是双端队列,扩展了Queue
,支持两端操作操作能力:
Queue
只有队头出队(poll
)、队尾入队(offer
)
Deque
增加offerFirst/pollFirst
等双端操作方法栈功能:
Deque
可直接作为栈使用(push
/pop
方法)
Queue
没有原生栈操作支持
Q2:ArrayDeque和LinkedList如何选择?
A:
ArrayDeque:
基于循环数组,内存连续
两端操作时间复杂度O(1)
随机访问更快,CPU缓存友好
推荐场景:大多数队列/栈需求(默认选择)
LinkedList:
基于双向链表,内存分散
支持
List
接口的索引访问插入删除中间元素更高效
推荐场景:
需要同时使用队列和列表功能
需要频繁在中间位置插入/删除
Q3:阻塞队列是什么?常用实现有哪些?
A:
阻塞队列 :当队列满时阻塞生产者,队列空时阻塞消费者(
BlockingQueue
接口)常用实现:
ArrayBlockingQueue
:数组实现的有界队列
LinkedBlockingQueue
:链表实现的可选有界队列
PriorityBlockingQueue
:带优先级的无界阻塞队列
SynchronousQueue
:不存储元素的直接传递队列
Q4:Deque如何替代Stack?
A:
Java官方推荐用
Deque
替代Stack
类转换方式:
javaDeque<Integer> stack = new ArrayDeque<>(); stack.push(1); // 入栈 = addFirst() int top = stack.peek(); // 查看栈顶 = peekFirst() int pop = stack.pop(); // 出栈 = removeFirst()
优势:
避免
Stack
的同步开销(Vector
实现)更统一的集合API
更好的性能(特别是
ArrayDeque
)
Q5:PriorityQueue的排序原理?
A:
基于堆数据结构(默认最小堆)
排序规则:
自然排序:元素实现
Comparable
定制排序:构造时传入
Comparator
特点:
队头总是当前最值元素
入队/出队时间复杂度O(log n)
不支持
null
元素
Q6:如何使用Deque同时作为队列和栈?
A:
Deque可以同时支持队列和栈操作,但必须避免混用API:
- 队列模式(FIFO):固定使用尾部添加+头部移除组合
java// 推荐API组合 deque.offer(e); // 入队(尾部) String item = deque.poll(); // 出队(头部)
- 栈模式(LIFO):固定使用头部添加+头部移除组合
java// 推荐API组合 deque.push(e); // 入栈(头部) String top = deque.pop(); // 出栈(头部)
- 危险操作:混用API会导致数据顺序混乱
java// 错误示例(导致数据顺序不可预测) deque.push("A"); // 栈操作(头部插入) deque.offer("B"); // 队列操作(尾部插入) // 此时队列:A<-B,但栈顶是A
Q7:为什么Java推荐用Deque代替Stack类?
A:
除了之前提到的性能优势,API设计也更合理:
Stack的缺陷API:
java// 老式Stack API(继承自Vector) stack.addElement(e); // 非标准方法名 stack.insertElementAt(e, 0); // 危险的低效操作
Deque的标准栈API:
javadeque.push(e); // 标准栈操作 deque.pop(); // 直观的LIFO语义 deque.peek(); // 查看栈顶
额外优势 :Deque的栈操作时间复杂度均为O(1),而Stack的
insertElementAt(0)
是O(n)
七、高频面试进阶问题
-
poll()
和remove()
有什么区别?-
行为相同:移除并返回队头元素
-
空队列时:
poll()
返回null
,remove()
抛异常
-
-
ArrayDeque
初始容量是多少?如何扩容?-
默认初始容量16
-
扩容规则:加倍容量(16→32→64...)
-
重要特性:容量总是2的幂(位运算优化)
-
-
阻塞队列的
put()
和offer()
区别?java// 阻塞方法(无限等待) void put(E e) throws InterruptedException; // 非阻塞方法 boolean offer(E e, long timeout, TimeUnit unit); // 限时等待 boolean offer(E e); // 立即返回
-
为什么
LinkedList
实现了List
和Deque
?-
设计上支持多种访问方式:
-
列表功能:索引访问/中间插入
-
队列功能:FIFO操作
-
双端功能:两端高效操作
-
-
体现了接口隔离原则
-