Deque是Java集合框架中定义的双端队列接口,全称为Double Ended Queue,它继承了Queue接口,支持在队列的两端进行元素的插入、删除和查看操作。基于这些特性,Deque可以很方便地模拟栈和队列两种经典数据结构的行为,而且相比传统的Stack类和Queue接口的实现,Deque的使用更加灵活安全。

Deque的核心方法分类
Deque提供了一系列操作两端元素的方法,按照操作失败时的处理方式可以分为两类:一类是操作失败时抛出异常,另一类是操作失败时返回特殊值(null或false)。具体方法对应关系如下:
| 操作类型 | 队首操作(失败时抛异常) | 队首操作(失败时返回特殊值) | 队尾操作(失败时抛异常) | 队尾操作(失败时返回特殊值) |
|---|---|---|---|---|
| 插入元素 | addFirst(e) | offerFirst(e) | addLast(e) | offerLast(e) |
| 删除元素 | removeFirst() | pollFirst() | removeLast() | pollLast() |
| 查看元素 | getFirst() | peekFirst() | getLast() | peekLast() |
使用Deque实现栈操作
栈是一种后进先出(LIFO)的数据结构,核心操作包括入栈、出栈、查看栈顶元素。使用Deque实现栈时,我们只需要操作队列的一端即可,通常选择队首作为栈顶,对应的方法选择如下:
- 入栈:对应
push(e)方法,等价于addFirst(e),将元素插入到队首 - 出栈:对应
pop()方法,等价于removeFirst(),移除并返回队首元素 - 查看栈顶:对应
peek()方法,等价于peekFirst(),返回队首元素但不移除
下面是使用Deque实现栈操作的完整代码示例:
import java.util.ArrayDeque;
import java.util.Deque;
public class DequeStackExample {
public static void main(String[] args) {
// 创建Deque实例,作为栈使用
Deque<String> stack = new ArrayDeque<>();
// 入栈操作
stack.push("Java");
stack.push("Python");
stack.push("C++");
System.out.println("入栈后栈内容:" + stack); // 输出 [C++, Python, Java]
// 查看栈顶元素
String top = stack.peek();
System.out.println("当前栈顶元素:" + top); // 输出 C++
// 出栈操作
String popped = stack.pop();
System.out.println("出栈的元素:" + popped); // 输出 C++
System.out.println("出栈后栈内容:" + stack); // 输出 [Python, Java]
}
}
使用Deque实现队列操作
队列是一种先进先出(FIFO)的数据结构,核心操作包括入队、出队、查看队头元素。使用Deque实现队列时,我们约定队尾为插入端,队首为删除和查看端,对应的方法选择如下:
- 入队:对应
add(e)或offer(e)方法,等价于addLast(e)或offerLast(e),将元素插入到队尾 - 出队:对应
remove()或poll()方法,等价于removeFirst()或pollFirst(),移除并返回队首元素 - 查看队头:对应
element()或peek()方法,等价于getFirst()或peekFirst(),返回队首元素但不移除
下面是使用Deque实现队列操作的完整代码示例:
import java.util.ArrayDeque;
import java.util.Deque;
public class DequeQueueExample {
public static void main(String[] args) {
// 创建Deque实例,作为队列使用
Deque<Integer> queue = new ArrayDeque<>();
// 入队操作
queue.offer(10);
queue.offer(20);
queue.offer(30);
System.out.println("入队后队列内容:" + queue); // 输出 [10, 20, 30]
// 查看队头元素
Integer head = queue.peek();
System.out.println("当前队头元素:" + head); // 输出 10
// 出队操作
Integer polled = queue.poll();
System.out.println("出队的元素:" + polled); // 输出 10
System.out.println("出队后队列内容:" + queue); // 输出 [20, 30]
}
}
Deque对比传统实现的优势
在Java中,传统实现栈可以使用java.util.Stack类,实现队列可以使用java.util.LinkedList作为Queue接口的实例,但Deque的实现方式有更多优势:
- Stack类是线程同步的,性能较差,而Deque的实现类如ArrayDeque是非同步的,性能更优,需要线程安全时可以配合Collections工具类处理
- Stack类继承了Vector类,暴露了很多不适合栈操作的方法,容易被误用,Deque的方法设计更贴合双端队列和栈、队列的操作语义
- Deque同时支持栈和队列的操作,使用起来更加灵活,不需要针对不同数据结构选择不同的类
使用注意事项
在实际使用Deque时,需要注意以下几点:
- Deque的实现类如ArrayDeque不支持存储null元素,如果尝试插入null会抛出NullPointerException,而LinkedList作为Deque实现时可以存储null,但一般不建议这么做
- 选择具体实现类时,如果不需要遍历中间元素,ArrayDeque的性能和内存占用通常优于LinkedList
- 如果明确只需要栈操作,不要使用队列相关的方法,反之亦然,保持代码的语义清晰
Java官方文档也推荐使用Deque替代传统的Stack类来实现栈功能,因为Deque的实现更加完善,设计更合理。