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对象转JSON时动态的增删改查属性详解

    Java对象转JSON时动态的增删改查属性详解

    这篇文章主要介绍了Java对象转JSON时如何动态的增删改查属性的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • java并发编程中实现可见性的四种可行方案解析

    java并发编程中实现可见性的四种可行方案解析

    这篇文章主要介绍了java并发编程中实现可见性的四种可行方案解析,使用关键字volatile和使用锁(如synchronized关键字或者java.util.concurrent包中的锁)来确保对共享变量的修改在多线程环境中能够正确地被其他线程所观察到,需要的朋友可以参考下
    2023-08-08
  • java-SSH2实现数据库和界面的分页

    java-SSH2实现数据库和界面的分页

    本文主要是介绍SSH2实现数据库和界面的分页的代码,分页在web应用中是经常要做的事情,实用性比较大,有需要的朋友可以来了解一下。
    2016-10-10
  • Spring实例化bean的方式代码详解

    Spring实例化bean的方式代码详解

    这篇文章主要介绍了Spring实例化bean的方式代码详解,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • SpringCloud使用Zookeeper作为注册中心

    SpringCloud使用Zookeeper作为注册中心

    这篇文章主要介绍了SpringCloud如何使用Zookeeper作为注册中心,帮助大家更好的理解和学习使用Zookeeper,感兴趣的朋友可以了解下
    2021-04-04
  • java使用Logback配置输出日志内容到文件示例代码

    java使用Logback配置输出日志内容到文件示例代码

    这篇文章主要介绍了java Logback输出日志内容到文件,要将logger.info的信息输出到文件,您可以使用Logback配置,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-09-09
  • Hadoop MapReduce实现单词计数(Word Count)

    Hadoop MapReduce实现单词计数(Word Count)

    这篇文章主要为大家详细介绍了如何利用Hadoop实现单词计数(Word Count)的MapReduce,文中的示例代码讲解详细,感兴趣的可以跟随小编一起学习一下
    2023-05-05
  • Java子线程无法获取Attributes的解决方法(最新推荐)

    Java子线程无法获取Attributes的解决方法(最新推荐)

    在Java多线程编程中,子线程无法直接获取主线程设置的Attributes是一个常见问题,本文探讨了这一问题的原因,并提供了两种解决方案,对Java子线程无法获取Attributes的解决方案感兴趣的朋友一起看看吧
    2025-01-01
  • Java雪花算法的实现详解

    Java雪花算法的实现详解

    雪花算法(Snowflake)是一种分布式唯一ID生成算法,用于生成全局唯一的ID,使用雪花算法生成的ID通常是一个64位的整数,可以根据需要进行转换和展示,在Java等编程语言中,可以使用相应的库或工具来生成雪花算法的ID,本文给大家介绍了Java雪花算法的实现
    2023-11-11
  • Java并发工具类CountDownLatch CyclicBarrier使用详解

    Java并发工具类CountDownLatch CyclicBarrier使用详解

    这篇文章主要为大家介绍了Java并发工具类CountDownLatch CyclicBarrier使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06

最新评论