一、为何选择Deque?超越Stack与Queue的局限

Java传统Stack类因同步开销大、设计过时被官方建议弃用;Queue仅支持单向操作。Deque作为双端队列,完美融合栈(LIFO)与队列(FIFO)特性,提供首尾O(1)复杂度的插入/删除。

// 创建ArrayDeque(推荐无界场景)
Deque<String> deque = new ArrayDeque<>(); 

二、核心操作:双端四向进出

操作类型

队首方法

队尾方法

行为差异

插入

addFirst(e)

addLast(e)

失败抛异常

offerFirst(e)

offerLast(e)

失败返false

删除

removeFirst()

removeLast()

空队列抛异常

pollFirst()

pollLast()

空队列返null

检查

getFirst()

getLast()

空队列抛异常

peekFirst()

peekLast()

空队列返null


三、实战场景:代码示例解析

1️⃣ 替代Queue实现BFS
Deque<TreeNode> queue = new ArrayDeque<>();
queue.offer(root); // 队尾入队
while (!queue.isEmpty()) {
    TreeNode node = queue.pollFirst(); // 队首出队
    if (node.left != null) queue.offer(node.left);
    if (node.right != null) queue.offer(node.right);
}
2️⃣ 替代Stack实现括号匹配
Deque<Character> stack = new ArrayDeque<>();
for (char c : s.toCharArray()) {
    if (c == '(') stack.addLast(c);
    else if (c == ')') {
        if (stack.isEmpty() || stack.pollLast() != '(') 
            return false;
    }
}
return stack.isEmpty();
3️⃣ 滑动窗口最大值(单调队列)
Deque<Integer> maxDeque = new ArrayDeque<>();
for (int i = 0; i < nums.length; i++) {
    // 维护单调递减队列
    while (!maxDeque.isEmpty() && nums[i] > nums[maxDeque.peekLast()]) {
        maxDeque.pollLast();
    }
    maxDeque.offerLast(i);
    // 移除越界队首
    if (maxDeque.peekFirst() == i - k) maxDeque.pollFirst();
    if (i >= k - 1) result[i - k + 1] = nums[maxDeque.peekFirst()];
}

四、进阶:线程安全与性能选型

实现类

数据结构

随机访问

内存占用

线程安全

适用场景

ArrayDeque

循环数组

O(1)

低

❌

高频操作的单线程环境

LinkedList

双向链表

O(n)

较高

❌

需要频繁插入删除

LinkedBlockingDeque

链表

O(n)

高

✅

高并发阻塞队列

最佳实践:多数场景优选ArrayDeque;需要阻塞操作或线程安全时使用LinkedBlockingDeque。


结语:双端之力,掌控数据结构自由

Deque凭借其灵活的双端操作能力,成为Java集合框架中高效且多用途的利器。无论是替代传统的栈/队列,还是解决滑动窗口等算法问题,合理选择ArrayDeque或LinkedList能显著提升代码性能与可读性。掌握此“双端利刃”,轻松应对复杂数据流挑战! 🚀

更多推荐