当前位置: 首页 > news >正文

数据结构 - Java 队列

Java中的队列

队列是Java集合框架中的一种重要数据结构,用于按照特定顺序存储和处理元素,通常遵循先进先出(FIFO)原则。Java提供了丰富的队列实现,适用于不同场景。

Queue接口
Queue是Java集合框架中的一个基础接口,继承自Collection接口,定义了队列的基本操作:

import java.util.Queue;
import java.util.LinkedList;
import java.util.ArrayDeque;
import java.util.PriorityQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import java.util.Comparator;
import java.util.Deque;
import java.util.concurrent.PriorityBlockingQueue;public class JavaQueueExamples {public static void main(String[] args) {// 1. 基本队列操作示例basicQueueOperations();// 2. 常用队列实现示例queueImplementations();// 3. 阻塞队列示例blockingQueueExample();// 4. 延迟队列示例delayQueueExample();// 5. 双端队列示例dequeExample();// 6. 优先级队列示例priorityQueueExample();}// 1. 基本队列操作public static void basicQueueOperations() {System.out.println("\n=== 基本队列操作 ===");Queue<String> queue = new LinkedList<>();// 添加元素queue.add("第一个"); // 添加成功返回true,队列满则抛出异常queue.offer("第二个"); // 添加成功返回true,队列满则返回false// 查看队首元素但不移除System.out.println("队首元素(peek): " + queue.peek()); // 队列为空返回nullSystem.out.println("队首元素(element): " + queue.element()); // 队列为空抛出异常// 移除并返回队首元素System.out.println("移除队首(poll): " + queue.poll()); // 队列为空返回nullSystem.out.println("移除队首(remove): " + queue.remove()); // 队列为空抛出异常System.out.println("队列是否为空: " + queue.isEmpty());}// 2. 常用队列实现public static void queueImplementations() {System.out.println("\n=== 常用队列实现 ===");// LinkedList实现的队列Queue<String> linkedListQueue = new LinkedList<>();linkedListQueue.offer("LinkedList队列元素1");linkedListQueue.offer("LinkedList队列元素2");System.out.println("LinkedList队列: " + linkedListQueue);// ArrayDeque实现的队列 (更高效)Queue<String> arrayDequeQueue = new ArrayDeque<>();arrayDequeQueue.offer("ArrayDeque队列元素1");arrayDequeQueue.offer("ArrayDeque队列元素2");System.out.println("ArrayDeque队列: " + arrayDequeQueue);}// 3. 阻塞队列示例public static void blockingQueueExample() {System.out.println("\n=== 阻塞队列示例 ===");// 有界阻塞队列BlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(2);try {arrayBlockingQueue.put("任务1");arrayBlockingQueue.put("任务2");System.out.println("ArrayBlockingQueue: " + arrayBlockingQueue);// 如果队列已满,put方法会阻塞// arrayBlockingQueue.put("任务3"); // 会阻塞直到有空间// 使用offer方法添加,可以设置超时时间boolean added = arrayBlockingQueue.offer("任务3", 1, TimeUnit.SECONDS);System.out.println("添加任务3是否成功: " + added);// 取出元素String task = arrayBlockingQueue.take(); // 如果队列为空,take方法会阻塞System.out.println("取出任务: " + task);// 使用poll方法取出,可以设置超时时间String task2 = arrayBlockingQueue.poll(1, TimeUnit.SECONDS);System.out.println("取出任务2: " + task2);} catch (InterruptedException e) {e.printStackTrace();}// 无界阻塞队列BlockingQueue<String> linkedBlockingQueue = new LinkedBlockingQueue<>();linkedBlockingQueue.offer("LinkedBlockingQueue元素");System.out.println("LinkedBlockingQueue: " + linkedBlockingQueue);}// 4. 延迟队列示例public static void delayQueueExample() {System.out.println("\n=== 延迟队列示例 ===");DelayQueue<DelayedElement> delayQueue = new DelayQueue<>();// 添加延迟元素,分别延迟1秒、2秒、3秒delayQueue.offer(new DelayedElement("任务1", 1000));delayQueue.offer(new DelayedElement("任务2", 2000));delayQueue.offer(new DelayedElement("任务3", 3000));System.out.println("延迟队列大小: " + delayQueue.size());try {// 尝试获取,但只有延迟到期的元素才能被取出System.out.println("开始获取延迟队列元素...");// 获取并移除第一个可用的元素DelayedElement element1 = delayQueue.take();System.out.println("取出元素: " + element1.getName() + ", 时间: " + System.currentTimeMillis());// 获取并移除第二个可用的元素DelayedElement element2 = delayQueue.take();System.out.println("取出元素: " + element2.getName() + ", 时间: " + System.currentTimeMillis());// 使用poll带超时的方法获取第三个元素DelayedElement element3 = delayQueue.poll(5, TimeUnit.SECONDS);if (element3 != null) {System.out.println("取出元素: " + element3.getName() + ", 时间: " + System.currentTimeMillis());} else {System.out.println("超时未获取到元素");}} catch (InterruptedException e) {e.printStackTrace();}}// 5. 双端队列示例public static void dequeExample() {System.out.println("\n=== 双端队列示例 ===");Deque<String> deque = new ArrayDeque<>();// 在队首和队尾添加元素deque.offerFirst("队首元素1");deque.offerLast("队尾元素1");deque.offerFirst("队首元素2");deque.offerLast("队尾元素2");System.out.println("双端队列: " + deque); // [队首元素2, 队首元素1, 队尾元素1, 队尾元素2]// 查看队首和队尾元素System.out.println("队首元素: " + deque.peekFirst());System.out.println("队尾元素: " + deque.peekLast());// 移除队首和队尾元素System.out.println("移除队首: " + deque.pollFirst());System.out.println("移除队尾: " + deque.pollLast());System.out.println("处理后的双端队列: " + deque);// 使用栈方法 (LIFO)deque.push("栈顶元素"); // 等同于addFirst()System.out.println("添加栈顶元素后: " + deque);System.out.println("弹出栈顶: " + deque.pop()); // 等同于removeFirst()System.out.println("弹出后的队列: " + deque);}// 6. 优先级队列示例public static void priorityQueueExample() {System.out.println("\n=== 优先级队列示例 ===");// 自然排序的优先级队列 (小顶堆)PriorityQueue<Integer> minHeap = new PriorityQueue<>();minHeap.offer(10);minHeap.offer(5);minHeap.offer(15);minHeap.offer(1);System.out.print("自然排序优先级队列出队顺序: ");while (!minHeap.isEmpty()) {System.out.print(minHeap.poll() + " ");}System.out.println();// 自定义比较器的优先级队列 (大顶堆)PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());maxHeap.offer(10);maxHeap.offer(5);maxHeap.offer(15);maxHeap.offer(1);System.out.print("自定义排序优先级队列出队顺序: ");while (!maxHeap.isEmpty()) {System.out.print(maxHeap.poll() + " ");}System.out.println();// 使用对象和自定义比较器PriorityQueue<Task> taskQueue = new PriorityQueue<>((t1, t2) -> t1.getPriority() - t2.getPriority());taskQueue.offer(new Task("普通任务", 3));taskQueue.offer(new Task("紧急任务", 1));taskQueue.offer(new Task("低优先级任务", 5));taskQueue.offer(new Task("高优先级任务", 2));System.out.println("任务优先级队列出队顺序: ");while (!taskQueue.isEmpty()) {System.out.println(taskQueue.poll());}// 线程安全的优先级阻塞队列PriorityBlockingQueue<Integer> priorityBlockingQueue = new PriorityBlockingQueue<>();priorityBlockingQueue.offer(10);priorityBlockingQueue.offer(5);priorityBlockingQueue.offer(15);System.out.println("PriorityBlockingQueue: " + priorityBlockingQueue);}
}

// 延迟队列元素类

class DelayedElement implements Delayed {private String name;private long expireTime; // 过期时间,单位毫秒public DelayedElement(String name, long delayInMillis) {this.name = name;this.expireTime = System.currentTimeMillis() + delayInMillis;}public String getName() {return name;}@Overridepublic long getDelay(TimeUnit unit) {// 计算剩余延迟时间long diff = expireTime - System.currentTimeMillis();return unit.convert(diff, TimeUnit.MILLISECONDS);}@Overridepublic int compareTo(Delayed other) {// 比较延迟时间if (other == this) {return 0;}if (other instanceof DelayedElement) {DelayedElement otherElement = (DelayedElement) other;return Long.compare(expireTime, otherElement.expireTime);}long diff = getDelay(TimeUnit.MILLISECONDS) - other.getDelay(TimeUnit.MILLISECONDS);return (diff == 0) ? 0 : ((diff < 0) ? -1 : 1);}@Overridepublic String toString() {return "DelayedElement{name='" + name + "', expireTime=" + expireTime + "}";}
}

// 任务类(用于优先级队列示例)

class Task {private String name;private int priority; // 优先级,数字越小优先级越高public Task(String name, int priority) {this.name = name;this.priority = priority;}public String getName() {return name;}public int getPriority() {return priority;}@Overridepublic String toString() {return "Task{name='" + name + "', priority=" + priority + "}";}
}

Queue接口的核心方法

Queue接口定义了两组核心操作方法,它们在不同情况下的行为略有不同:

操作抛出异常返回特殊值

添加元素add(e)offer(e)
移除元素remove()poll()
检查元素element()peek()

常见的队列实现

Java提供了多种队列实现,适合不同的应用场景:

  1. 非阻塞队列
    LinkedList: 基于链表的队列实现,适合频繁添加/删除操作
    ArrayDeque: 基于数组的双端队列,通常比LinkedList性能更好
    PriorityQueue: 优先级队列,基于堆实现,元素按优先级出队

  2. 阻塞队列 (BlockingQueue)
    阻塞队列支持在队列为空/满时阻塞操作,非常适合生产者-消费者模式:

ArrayBlockingQueue: 有界阻塞队列,基于数组实现
LinkedBlockingQueue: 可选有界阻塞队列,基于链表实现
PriorityBlockingQueue: 无界优先级阻塞队列
DelayQueue: 延迟队列,元素只有到达指定延迟时间才能被取出
SynchronousQueue: 没有容量的阻塞队列,每个插入操作必须等待相应的移除操作

  1. 双端队列 (Deque)
    双端队列允许在两端进行插入和移除操作:

ArrayDeque: 基于数组的可调整大小的双端队列
LinkedList: 也实现了Deque接口
LinkedBlockingDeque: 线程安全的双端阻塞队列

队列的应用场景

任务调度:使用DelayQueue或PriorityQueue实现定时任务
线程池:阻塞队列用于存储等待执行的任务
消息队列:作为生产者-消费者之间的缓冲区
资源池:管理共享资源的分配和释放
缓存:实现LRU缓存等缓存策略
广度优先搜索:在图算法中使用队列进行BFS遍历

相关文章:

  • MybatisPlus-DQL查询+DML
  • Rust 学习笔记:处理任意数量的 future
  • Odoo 18 库存中管理最低安全库存规则(再订货规则)
  • 【WebSocket】WebSocket架构重构:从分散管理到统一连接的实战经验
  • 【EdgeAI实战】(3)边缘AI开发套件 STM32N6570X0 用户手册
  • Jenkins 配置gitlab的 pipeline流水线任务
  • reactive() 和 toRef()
  • VR 地震安全演练:“透视” 地震,筑牢企业安全新护盾​
  • 单连杆倾角估计:互补滤波器的 MATLAB 仿真实现
  • jenkins流水线打包vue无权限
  • VR百科:实景三维重建
  • Linux系统下安装elasticsearch6.8并配置ik分词
  • Vue3+PDF.js 实现高性能 PDF 阅读器开发实战
  • VSCode占C盘内存太大,如何处理
  • 2025最新版使用VSCode和CMake图形化编译调试Cuda C++程序(保姆级教学)
  • vba学习系列(11)--批退率通过率等数据分析
  • 企业级人员评价系统Web端重构实战:前端架构效能升级
  • OpenCV 图像几何形状绘制
  • LMD分解通过局部均值分解重构信号实现对信号的降噪
  • MySQL数据库:关系型数据库的基石
  • wordpress 教育 演示/绍兴seo计费管理
  • 开封建站公司/域名查询 站长查询
  • 网站如何备案icp备案/国内免费建网站
  • 手机网站建设 cms/发帖推广哪个平台好
  • 做网站ps建立多大的画布/推广软文模板
  • 网站备案企业用个人来备案可以用吗/怎么免费建立网站