246. Java 集合 - 实现 Queue 和 Deque 的三大主力类
在 Java Collections Framework 中(不涉及并发编程领域),提供了三种主要实现,用来支持 Queue 和 Deque 接口:
| 实现类 | 支持接口 | 底层结构 | 特点 |
|---|---|---|---|
ArrayDeque | Queue + Deque | 动态数组 | 高效,无容量限制,推荐使用 |
LinkedList | Queue + Deque | 链表 | 适合频繁的头尾操作 |
PriorityQueue | Queue | 动态数组 + 排序 | 按顺序自动管理元素 |
📦 ArrayDeque —— 快速灵活的双端队列
- 支持:
Queue和Deque。 - 底层结构:使用动态数组。
- 特点:
- 容量会随着元素的增加自动扩展,不会拒绝插入。
- 适合做栈(
LIFO)和队列(FIFO)的高性能替代。 - 注意:
ArrayDeque不是线程安全的!
示例:使用 ArrayDeque 作为栈
import java.util.ArrayDeque;
import java.util.Deque;
public class ArrayDequeAsStack {
public static void main(String[] args) {
Deque<Integer> stack = new ArrayDeque<>();
stack.push(10);
stack.push(20);
stack.push(30);
System.out.println(stack.pop()); // 30
System.out.println(stack.peek()); // 20
}
}
🔗 LinkedList —— 万能链表版队列/栈
- 支持:
Queue和Deque。 - 底层结构:双向链表。
- 特点:
- 插入和删除首尾元素操作非常高效。
- 可以同时作为队列、双端队列、或者栈使用。
- 同时也是一个
List,可以按索引访问元素(不过随机访问速度较慢)。
示例:使用 LinkedList 作为双端队列
import java.util.LinkedList;
import java.util.Deque;
public class LinkedListAsDeque {
public static void main(String[] args) {
Deque<String> deque = new LinkedList<>();
deque.addFirst("A");
deque.addLast("B");
deque.addFirst("C");
System.out.println(deque.pollFirst()); // C
System.out.println(deque.pollLast()); // B
}
}
🏆 PriorityQueue —— 带自动排序的优先级队列
- 支持:仅支持
Queue(不支持Deque)。 - 底层结构:基于**堆(Heap)**的动态数组。
- 特点:
- 元素会按照自然顺序或指定 Comparator 顺序自动排序。
- 队列头(Head)始终是**最小(优先级最高)**的元素。
- 插入元素时重新维护顺序。
- 容量也会自动扩展。
示例:使用 PriorityQueue
import java.util.PriorityQueue;
import java.util.Queue;
public class PriorityQueueExample {
public static void main(String[] args) {
Queue<Integer> pq = new PriorityQueue<>();
pq.offer(30);
pq.offer(10);
pq.offer(20);
System.out.println(pq.poll()); // 10 (最小的先出)
System.out.println(pq.peek()); // 20
}
}
🎯 小结比较
| 类 | 适合场景 | 是否有序 | 动态扩容 | 特点总结 |
|---|---|---|---|---|
ArrayDeque | 普通队列 / 栈,需高性能 | 否 | 是 | 最推荐的一般用途 Deque |
LinkedList | 需要频繁插入删除首尾元素 | 否 | 是 | 灵活但占内存较大 |
PriorityQueue | 需要按优先级出队,比如调度系统 | 是 | 是 | 元素自动排序 |
🧐 互动问题
问题1:为什么 PriorityQueue 不能当作栈(LIFO)来使用?
因为
PriorityQueue总是自动根据元素大小排序,无法保证后进先出(LIFO)的顺序。
问题2:在使用 ArrayDeque 时,如果不断增加元素,会发生什么?
数组会自动扩容,不会抛出异常。