📚 Java 23 集合框架详解:Deque 接口及实现类(ArrayDeque、LinkedList)
📖 1. 概述
Deque(Double-Ended Queue) 接口是 Java 集合框架中用于实现 双端队列 的接口,它支持在 队列头部和尾部插入和删除元素。与 Queue 接口不同,Deque 支持 双向操作,可以充当 栈(LIFO) 和 队列(FIFO)。
🔑 主要实现类
ArrayDeque:基于 数组 的双端队列实现,性能高,适用于大多数场景。LinkedList:基于 双向链表 的双端队列实现,插入和删除性能好,适用于频繁操作头尾元素的场景。
📋 2. Deque 接口常用方法
| 方法 | 描述 |
|---|---|
addFirst(E e) | 将元素插入到队列头部 |
addLast(E e) | 将元素插入到队列尾部 |
offerFirst(E e) | 将元素插入到队列头部(不抛异常) |
offerLast(E e) | 将元素插入到队列尾部(不抛异常) |
removeFirst() | 移除并返回队列头部的元素 |
removeLast() | 移除并返回队列尾部的元素 |
pollFirst() | 获取并移除队列头部的元素(为空返回 null) |
pollLast() | 获取并移除队列尾部的元素(为空返回 null) |
getFirst() | 获取但不移除队列头部的元素 |
getLast() | 获取但不移除队列尾部的元素 |
📋 3. ArrayDeque 详解
✅ 3.1 特点
- 基于数组实现,可动态扩容。
- 不允许存储
null值。 - 性能优于
LinkedList,特别是在作为 栈 或 队列 使用时。 - 提供了比
Stack更好的替代方案。
🔧 3.2 使用案例
✅ 作为队列使用(FIFO)
import java.util.ArrayDeque;
public class ArrayDequeQueueExample {
public static void main(String[] args) {
ArrayDeque<String> queue = new ArrayDeque<>();
// 添加元素到队列尾部
queue.offer("Alice");
queue.offer("Bob");
queue.offer("Charlie");
// 遍历队列
System.out.println("Queue Elements:");
queue.forEach(System.out::println);
// 获取并移除队列头部元素
System.out.println("Polled Element: " + queue.poll());
// 查看队列头部元素
System.out.println("Peek Element: " + queue.peek());
}
}
输出:
Queue Elements:
Alice
Bob
Charlie
Polled Element: Alice
Peek Element: Bob
✅ 作为栈使用(LIFO)
import java.util.ArrayDeque;
public class ArrayDequeStackExample {
public static void main(String[] args) {
ArrayDeque<String> stack = new ArrayDeque<>();
// 添加元素到栈顶
stack.push("Alice");
stack.push("Bob");
stack.push("Charlie");
// 遍历栈
System.out.println("Stack Elements:");
stack.forEach(System.out::println);
// 获取并移除栈顶元素
System.out.println("Popped Element: " + stack.pop());
// 查看栈顶元素
System.out.println("Peek Element: " + stack.peek());
}
}
输出:
Stack Elements:
Charlie
Bob
Alice
Popped Element: Charlie
Peek Element: Bob
🛠 3.3 优化方案
- 避免存储
null值,因为ArrayDeque不支持null。 - 优先使用
ArrayDeque代替Stack,因为Stack是一个老旧的类,性能较低且不推荐使用。
⚠️ 3.4 多线程优化
ArrayDeque 是 线程不安全的,如果在多线程环境中使用,可以使用 ConcurrentLinkedDeque。
📋 4. LinkedList 详解
✅ 4.1 特点
- 基于双向链表实现,支持高效的插入和删除操作。
- 允许存储
null值。 - 既可以用作 列表,也可以用作 双端队列。
🔧 4.2 使用案例
✅ 作为队列使用(FIFO)
import java.util.LinkedList;
import java.util.Deque;
public class LinkedListQueueExample {
public static void main(String[] args) {
Deque<String> queue = new LinkedList<>();
// 添加元素到队列尾部
queue.offer("Alice");
queue.offer("Bob");
queue.offer("Charlie");
// 遍历队列
System.out.println("Queue Elements:");
queue.forEach(System.out::println);
// 获取并移除队列头部元素
System.out.println("Polled Element: " + queue.poll());
// 查看队列头部元素
System.out.println("Peek Element: " + queue.peek());
}
}
✅ 作为栈使用(LIFO)
import java.util.LinkedList;
public class LinkedListStackExample {
public static void main(String[] args) {
LinkedList<String> stack = new LinkedList<>();
// 添加元素到栈顶
stack.push("Alice");
stack.push("Bob");
stack.push("Charlie");
// 遍历栈
System.out.println("Stack Elements:");
stack.forEach(System.out::println);
// 获取并移除栈顶元素
System.out.println("Popped Element: " + stack.pop());
// 查看栈顶元素
System.out.println("Peek Element: " + stack.peek());
}
}
🛠 4.3 优化方案
- 避免频繁随机访问,因为
LinkedList的随机访问性能较差。 - 优先使用
ArrayDeque,如果不需要存储大量元素且对内存占用敏感。
⚠️ 4.4 多线程优化
LinkedList 是 线程不安全的,在多线程环境中可以使用 ConcurrentLinkedDeque。
🔄 5. 两者对比总结
| 特性 | ArrayDeque | LinkedList |
|---|---|---|
| 底层数据结构 | 动态数组 | 双向链表 |
是否允许 null 值 | 否 | 是 |
| 插入/删除性能 | 高 | 高 |
| 随机访问性能 | 高 | 低 |
| 适用场景 | 栈、队列操作 | 队列、列表操作 |
🎯 6. 选择指南
| 场景 | 推荐实现类 |
|---|---|
| 栈操作(LIFO) | ArrayDeque |
| 队列操作(FIFO) | ArrayDeque |
需要存储 null 值 | LinkedList |
| 频繁插入和删除操作 | LinkedList |
| 多线程环境 | ConcurrentLinkedDeque |
⚙️ 7. 总结
ArrayDeque是最推荐的双端队列实现,性能优于LinkedList,适用于大多数场景。LinkedList适用于需要存储null值或频繁插入和删除操作的场景。- 在多线程环境中,建议使用
ConcurrentLinkedDeque代替。
1103

被折叠的 条评论
为什么被折叠?



