Java中Queue以及Deque用法示例详解

 更新时间:2025年08月29日 09:49:15   作者:xzkyd outpaper  
在Java集合框架中Queue和Deque接口是两种重要的数据结构,它们用于存储和管理元素序列,这篇文章主要介绍了Java中Queue以及Deque用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

一、核心概念与继承体系

二、Queue 核心方法与实现

1. 核心操作:

方法说明异常处理
offer(e)添加元素(推荐)失败返回false
add(e)添加元素失败抛IllegalStateException
poll()移除并返回队头元素空队列返回null
remove()移除并返回队头元素空队列抛NoSuchElementException
peek()查看队头元素(不删除)空队列返回null
element()查看队头元素(不删除)空队列抛NoSuchElementException

2. 常用实现类:

  • LinkedList:基于链表,支持null元素

  • PriorityQueue:基于堆的优先级队列(自然序/Comparator)

  • ArrayBlockingQueue:固定大小的阻塞队列(线程安全)

  • LinkedBlockingQueue:可选有界阻塞队列(线程安全)

三、Deque 双端队列扩展

1. 核心操作增强:

// 头部操作
offerFirst(e)  // 头部插入
pollFirst()    // 头部移除
peekFirst()    // 查看头部

// 尾部操作
offerLast(e)   // 尾部插入(等价于offer)
pollLast()     // 尾部移除
peekLast()     // 查看尾部

// 栈操作
push(e)        // = offerFirst(e)
pop()          // = removeFirst()

2. 作为队列使用(FIFO)的API:

// 队列操作(FIFO:先进先出)
offerLast(e) 或 offer(e)  // 入队(尾部添加)
pollFirst() 或 poll()     // 出队(头部移除)
peekFirst() 或 peek()     // 查看队头

3. 作为栈使用(LIFO)的API:

// 栈操作(LIFO:后进先出)
push(e)         // 入栈 = addFirst(e)
pop()           // 出栈 = removeFirst()
peekFirst()     // 查看栈顶

4. API使用对照表:

操作队列模式(FIFO)栈模式(LIFO)等效方法
添加元素offerLast(e) / offer(e)push(e)addFirst(e)(栈)
addLast(e)(队列)
移除元素pollFirst() / poll()pop()removeFirst()
查看元素peekFirst() / peek()peekFirst()getFirst()

5. 代码示例:

Deque<String> deque = new ArrayDeque<>();

// 作为队列使用(FIFO)
deque.offerLast("A"); // 队尾添加
deque.offerLast("B");
System.out.println(deque.pollFirst()); // A(队头移除)

// 作为栈使用(LIFO)
deque.push("C");      // 入栈
deque.push("D");
System.out.println(deque.pop());      // D(出栈)

// 混合操作(不推荐但可能)
deque.offerLast("E"); // 队尾添加(队列操作)
deque.push("F");      // 栈顶添加(栈操作)
System.out.println(deque.pollFirst()); // F(混合操作结果)

6. 常用实现类:

  • ArrayDeque:基于循环数组(默认容量16,性能最优)

  • LinkedList:基于双向链表(支持索引访问)

  • LinkedBlockingDeque:线程安全阻塞双端队列

四、与其他集合类对比

特性Queue/DequeListSetMap
数据结构线性序列线性序列哈希表/树键值对
元素顺序FIFO/LIFO/优先级插入顺序/索引无序/排序无序/键排序
重复元素允许允许不允许值允许,键不允许
空值支持部分实现支持允许HashSet允许HashMap允许值
访问方式端点访问索引/迭代器迭代器键访问
典型实现ArrayDeque, PriorityQueueArrayList, LinkedListHashSet, TreeSetHashMap, TreeMap

五、使用场景与最佳实践

1. 队列场景:

  • 任务调度:ThreadPoolExecutor 使用 BlockingQueue

  • 消息传递:生产者-消费者模式

  • 广度优先搜索(BFS)

2. 双端队列场景:

  • 撤销操作栈:ArrayDeque 替代 Stack

  • 滑动窗口算法

  • 工作窃取算法(Work Stealing)

3. 选择指南:

六、常见问题

Q1:Queue和Deque的主要区别是什么?

A:

  1. 功能定位

    • Queue 是标准FIFO队列(尾部添加,头部移除)

    • Deque 是双端队列,扩展了Queue,支持两端操作

  2. 操作能力

    • Queue 只有队头出队(poll)、队尾入队(offer)

    • Deque 增加offerFirst/pollFirst等双端操作方法

  3. 栈功能

    • Deque 可直接作为栈使用(push/pop方法)

    • Queue 没有原生栈操作支持

Q2:ArrayDeque和LinkedList如何选择?

A:

  • ArrayDeque

    • 基于循环数组,内存连续

    • 两端操作时间复杂度O(1)

    • 随机访问更快,CPU缓存友好

    • 推荐场景:大多数队列/栈需求(默认选择)

  • LinkedList

    • 基于双向链表,内存分散

    • 支持List接口的索引访问

    • 插入删除中间元素更高效

    • 推荐场景

      • 需要同时使用队列和列表功能

      • 需要频繁在中间位置插入/删除

Q3:阻塞队列是什么?常用实现有哪些?

A:

  • 阻塞队列:当队列满时阻塞生产者,队列空时阻塞消费者(BlockingQueue接口)

  • 常用实现

    • ArrayBlockingQueue:数组实现的有界队列

    • LinkedBlockingQueue:链表实现的可选有界队列

    • PriorityBlockingQueue:带优先级的无界阻塞队列

    • SynchronousQueue:不存储元素的直接传递队列

Q4:Deque如何替代Stack?

A:

  1. Java官方推荐用Deque替代Stack

  2. 转换方式:

    Deque<Integer> stack = new ArrayDeque<>();
    stack.push(1);          // 入栈 = addFirst()
    int top = stack.peek(); // 查看栈顶 = peekFirst()
    int pop = stack.pop();  // 出栈 = removeFirst()
  3. 优势

    • 避免Stack的同步开销(Vector实现)

    • 更统一的集合API

    • 更好的性能(特别是ArrayDeque

Q5:PriorityQueue的排序原理?

A:

  • 基于堆数据结构(默认最小堆)

  • 排序规则:

    • 自然排序:元素实现Comparable

    • 定制排序:构造时传入Comparator

  • 特点:

    • 队头总是当前最值元素

    • 入队/出队时间复杂度O(log n)

    • 不支持null元素

Q6:如何使用Deque同时作为队列和栈?

A:
Deque可以同时支持队列和栈操作,但必须避免混用API

  1. 队列模式(FIFO):固定使用尾部添加+头部移除组合

// 推荐API组合
deque.offer(e);      // 入队(尾部)
String item = deque.poll(); // 出队(头部)
  1. 栈模式(LIFO):固定使用头部添加+头部移除组合

// 推荐API组合
deque.push(e);       // 入栈(头部)
String top = deque.pop();  // 出栈(头部)
  1. 危险操作:混用API会导致数据顺序混乱

// 错误示例(导致数据顺序不可预测)
deque.push("A");  // 栈操作(头部插入)
deque.offer("B"); // 队列操作(尾部插入)
// 此时队列:A<-B,但栈顶是A

Q7:为什么Java推荐用Deque代替Stack类?

A:
除了之前提到的性能优势,API设计也更合理:

  1. Stack的缺陷API

    // 老式Stack API(继承自Vector)
    stack.addElement(e);  // 非标准方法名
    stack.insertElementAt(e, 0); // 危险的低效操作
  2. Deque的标准栈API

    deque.push(e);  // 标准栈操作
    deque.pop();    // 直观的LIFO语义
    deque.peek();   // 查看栈顶
  3. 额外优势:Deque的栈操作时间复杂度均为O(1),而Stack的insertElementAt(0)是O(n)

七、高频面试进阶问题

  1. poll()和remove()有什么区别?

    • 行为相同:移除并返回队头元素

    • 空队列时:poll()返回nullremove()抛异常

  2. ArrayDeque初始容量是多少?如何扩容?

    • 默认初始容量16

    • 扩容规则:加倍容量(16→32→64...)

    • 重要特性:容量总是2的幂(位运算优化)

  3. 阻塞队列的put()和offer()区别?

    // 阻塞方法(无限等待)
    void put(E e) throws InterruptedException;
    
    // 非阻塞方法
    boolean offer(E e, long timeout, TimeUnit unit); // 限时等待
    boolean offer(E e);                              // 立即返回
  4. 为什么LinkedList实现了List和Deque?

    • 设计上支持多种访问方式:

      • 列表功能:索引访问/中间插入

      • 队列功能:FIFO操作

      • 双端功能:两端高效操作

    • 体现了接口隔离原则

总结 

到此这篇关于Java中Queue以及Deque用法的文章就介绍到这了,更多相关Java中Queue以及Deque内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java设计模式之单例模式简介

    Java设计模式之单例模式简介

    这篇文章主要介绍了Java设计模式之单例模式简介,文中有非常详细的代码示例,对正在学习Java的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • Springboot源码 TargetSource解析

    Springboot源码 TargetSource解析

    这篇文章主要介绍了Springboot源码 TargetSource解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • 教你快速搭建sona服务及idea使用sona的方法

    教你快速搭建sona服务及idea使用sona的方法

    Sonar 是一个用于代码质量管理的开放平台。通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具,本文给大家分享搭建sona服务及idea使用sona的方法,感兴趣的朋友一起看看吧
    2021-06-06
  • Spring Security自定义失败处理器问题

    Spring Security自定义失败处理器问题

    这篇文章主要介绍了Spring Security自定义失败处理器问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 一起聊聊Java中的自定义异常

    一起聊聊Java中的自定义异常

    在学习Java的过程中,想必大家都一定学习过异常这个篇章,异常的基本特性和使用这里就不再多讲了。本文就来和大家讲讲如何自定义异常
    2022-08-08
  • Spring Boot整合阿里开源中间件Canal实现数据增量同步

    Spring Boot整合阿里开源中间件Canal实现数据增量同步

    这篇文章主要为大家介绍了Spring Boot整合阿里开源中间件Canal实现数据增量同步示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • SpringBoot中webSocket实现即时聊天

    SpringBoot中webSocket实现即时聊天

    这篇文章主要介绍了SpringBoot中webSocket实现即时聊天,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Java实现淘宝秒杀聚划算抢购自动提醒源码

    Java实现淘宝秒杀聚划算抢购自动提醒源码

    这篇文章主要为大家详细介绍了java实现淘宝秒杀聚划算抢购自动提醒源码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • java.lang.IncompatibleClassChangeError异常的问题解决

    java.lang.IncompatibleClassChangeError异常的问题解决

    本文主要介绍了java.lang.IncompatibleClassChangeError异常的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • 教你Spring Cloud保证各个微服务之间调用安全性

    教你Spring Cloud保证各个微服务之间调用安全性

    在微服务的架构下,系统会根据业务拆分为多个服务,各自负责单一的职责,在这样的架构下,我们需要确保各api的安全性,今天通过本文给大家分享Spring Cloud中如何保证各个微服务之间调用的安全性,需要的朋友参考下吧
    2021-08-08

最新评论