Deque
和 Stack
在 Java 里经常会拿来比较,因为它们都能做"栈"的工作,但实际上它们的设计理念和应用范围有很大区别。
📌 1. Stack
arduino
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.pop(); // 出栈 -> 2
-
继承关系 :
Stack
继承自Vector
(线程安全的动态数组)。 -
特点:
- 早期的栈实现(比较古老)。
- 方法都是同步的(
synchronized
),在多线程下保证安全。 - 但是因为同步的原因,单线程环境下效率会偏低。
- 只能作为 栈(LIFO) 使用。
📌 2. Deque
arduino
Deque<Integer> deque = new ArrayDeque<>();
deque.push(1); // 等价于 addFirst(1)
deque.push(2);
deque.pop(); // 出栈 -> 2
-
继承关系 :
Deque
是一个接口,代表 双端队列。 -
常见实现类 :
ArrayDeque
、LinkedList
。 -
特点:
-
比
Stack
新,推荐在栈场景中用Deque
代替Stack
。 -
方法没有同步锁,单线程环境下效率更高。
-
灵活:既能作为 栈(LIFO) 使用,也能作为 队列(FIFO) 使用。
addFirst() / removeFirst()
→ 栈操作。addLast() / removeFirst()
→ 队列操作。
-
📌 3. 主要区别总结
特性 | Stack | Deque (ArrayDeque/LinkedList) |
---|---|---|
数据结构 | 基于 Vector (数组 + 同步) |
双端队列(数组/链表实现) |
线程安全 | 线程安全(有同步锁) | 非线程安全(更快) |
使用场景 | 只能作为栈使用 | 既可栈,也可队列 |
推荐程度 | 过时,不推荐 | 官方推荐用它代替 Stack |
📌 4. 官方推荐
Java 官方文档明确说明:
For stack operations, use
Deque
instead ofStack
.
所以,在写 LeetCode 或一般算法题时:
ini
Deque<Integer> stack = new ArrayDeque<>();
是最佳选择。
好问题 👍,我们继续深入。
在 Java 里,Deque
是一个接口,而 ArrayDeque
和 LinkedList
是它的两个常用实现类。虽然都能实现 双端队列/栈,但它们的底层机制和性能差异很大。
📌 ArrayDeque vs LinkedList 对比
特性 | ArrayDeque | LinkedList |
---|---|---|
底层结构 | 动态数组(循环数组实现) | 双向链表 |
内存占用 | 连续内存,节省空间 | 每个节点额外存储 prev 和 next 指针,内存占用更大 |
随机访问 | 快(直接按索引访问 O(1)) | 慢(必须遍历链表 O(n)) |
插入/删除 | 在队列头尾 快(O(1),但数组可能扩容) | 在队列头尾 快(O(1),不需扩容) |
中间插入/删除 | 慢(需要移动元素 O(n)) | 快(只需改指针 O(1),但要先遍历找到位置 O(n)) |
缓存命中 | 高(数组连续存储,CPU 缓存友好) | 低(链表节点分散,可能导致 cache miss) |
扩容问题 | 容量不够时,会 自动扩容 2 倍 | 不需要扩容 |
线程安全 | 非线程安全 | 非线程安全 |
常见应用 | 栈/队列/单调栈(算法题推荐) | 需要频繁 在中间插入/删除 时使用 |
📌 代码示例
1. ArrayDeque
arduino
Deque<Integer> deque = new ArrayDeque<>();
deque.addFirst(1); // 插入到队首
deque.addLast(2); // 插入到队尾
System.out.println(deque.removeFirst()); // 1
System.out.println(deque.removeLast()); // 2
2. LinkedList
arduino
Deque<Integer> deque = new LinkedList<>();
deque.addFirst(1);
deque.addLast(2);
System.out.println(deque.removeFirst()); // 1
System.out.println(deque.removeLast()); // 2
两者用法几乎完全一致,因为都实现了 Deque
接口。
📌 选择建议
- 算法题 / LeetCode / 栈 / 队列 → ✅
ArrayDeque
(更快,更省内存) - 需要频繁在中间插入/删除 → ✅
LinkedList
(不用移动数组元素) - 几乎不用随机访问 ,只是做链表操作 →
LinkedList
也 OK,但一般性能不如ArrayDeque
💡 总结一句话:
👉 ArrayDeque
是通用高效的栈/队列实现,推荐首选。LinkedList
适合需要大量链表特性的场景。