Java队列详细解释

news2024/9/27 7:16:40

队列

一、什么是队列(Queue)

    ```java
    队列是一种线性数据结构,它的特点是先进先出。在队列中,元素的添加(入队)操作在队尾进行,而元素的移除(出队)操作则在队头进行。因此,队列可以被简单地描述为一个“先进先出”的容器。在Java中,队列接口继承自Collection接口,并提供了丰富的方法来操作队列中的元素
    ```

Java 的队列主要通过 java.util.Queue 接口及其子接口和实现类来定义和使用。根据不同的特性和用途,队列可以分为以下几类:

  1. 普通队列(FIFO 队列)

  2. 双端队列(Deque)

  3. 优先级队列(Priority Queue)

  4. 阻塞队列(Blocking Queue)

    提供阻塞操作,当队列为空时,获取元素的线程会等待;当队列已满时,添加元素的线程会等待。
    常用于生产者-消费者模式。
    
  5. 同步队列(Synchronous Queue)

SynchronousQueue 本质上是一个没有容量的队列,每个插入操作必须等待一个对应的移除操作,反之亦然。它常用于线程之间的直接交换数据。
不存储元素:
每个 put 必须等待一个 take,每个 take 必须等待一个 put。

如下:普通队列

在这里插入图片描述

在这里插入图片描述

在 Java 中,Queuejava.util 包下的一个接口,继承自 Collection 接口。Queue 定义了基本的队列操作方法,如添加、删除和查看元素。Queue 接口不能被直接实例化,但 Java 提供了多个实现类,例如 LinkedListPriorityQueueArrayDeque 等。

在这里插入图片描述

从上面类的继承关系图可以看到Queue是一个接口,它的内部主要定义了以下几个方法:

二、常用方法

在这里插入图片描述

1.offer( )和add( )方法的区别

Queue<String> queue = new LinkedList<>();
queue.add("A");
queue.offer("B");
// 队列中的元素:[A, B]

对于offer():往队列添加元素。在不违反容量限制的情况下立即执行,将指定的元素插入到队列中。如果队列已满直接返回false,队列未满则直接插入并返回true;
对于add():如果队列已满,抛出异常IllegalStateException。

2.poll( )和remove( )方法的区别

Queue<String> queue = new LinkedList<>();
queue.add("A");
queue.add("B");
String headElement = queue.remove();
// headElement 的值为 "A",队列中的元素:[B]

对于poll():检索并删除此队列的头,如果此队列为空,则返回 null ;
对于remove():检索并删除此队列的头。 此方法与poll不同之处在于,如果此队列为空,它将抛出异常。

3.peek()和element( )方法的区别

Queue<String> queue = new LinkedList<>();
queue.add("A");
queue.add("B");
String headElement = queue.element();
// headElement 的值为 "A",队列中的元素:[A, B]

对于peek():检索但不删除此队列的头部,如果此队列为空,则返回 null ;
对于element():检索但不删除这个队列的头。 此方法与peek的不同之处在于,如果此队列为空,它将抛出异常。

三、Java 中队列的实现类

Java 提供了多个 Queue 接口的实现,每种实现类都有不同的特点和应用场景。

1. LinkedList

LinkedList 类实现了 Queue 接口,并且可以作为队列使用。它是一个双向链表,支持队列的基本操作。LinkedList 适合频繁的插入和删除操作。

  • 特点
    • 动态大小,插入和删除操作性能较好。
  • 代码示例
import java.util.LinkedList;
import java.util.Queue;

public class LinkedListQueueExample {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();//多态
        // 添加元素
        queue.add("A");
        queue.add("B");
        queue.add("C");
        // 查看队列头部元素
        
        System.out.println("Queue head: " + queue.peek());
        // 移除元素
        
        System.out.println("Removed: " + queue.remove());

        // 查看队列内容
        System.out.println("Queue content: " + queue);
    }
}

输出

Queue head: A
Removed: A
Queue content: [B, C]

2. PriorityQueue 优先级队列

PriorityQueue 是一个基于堆的优先队列实现,它不会遵循普通的先进先出(FIFO)规则,而是根据元素的 优先级 来确定出队顺序。默认情况下,它是最小堆,即每次移除的是队列中的最小元素。

  • 特点

    • 不保证元素的顺序,插入元素根据优先级调整。
    • 插入元素时间复杂度为 O(log n),移除元素时间复杂度为 O(log n)
  • 代码示例

import java.util.PriorityQueue;
import java.util.Queue;

public class PriorityQueueExample {
    public static void main(String[] args) {
        Queue<Integer> queue = new PriorityQueue<>();

        // 添加元素
        queue.add(5);
        queue.add(2);
        queue.add(8);
        queue.add(1);

        // 移除并查看元素
        while (!queue.isEmpty()) {
            System.out.println("Removed: " + queue.poll());
        }
    }
}

输出

Removed: 1
Removed: 2
Removed: 5
Removed: 8

优先级案例

public class Task implements Comparable<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;
    }

    @Override
    public int compareTo(Task other) {
        return other.getPriority() - this.getPriority();
    }
}

import java.util.PriorityQueue;

public class Test {
    public static void main(String[] args) {
        PriorityQueue<Task> queue = new PriorityQueue<>();
        queue.add(new Task("Task 1", 5));
        queue.add(new Task("Task 2", 3));
        queue.add(new Task("Task 3", 10));
        queue.add(new Task("Task 4", 15));
        queue.add(new Task("Task 5", 1));
        while (!queue.isEmpty()) {
            Task task = queue.poll();
            String name = task.getName();
            System.out.println("Executing task: " + name);
        }
    }

}
添加元素时调用 compareTo 的原因
PriorityQueue 内部使用了 堆排序,通常是二叉堆,这是一种可以快速找到最大值或最小值的数据结构。在向堆中添加元素时,堆需要重新排序,以保持其“堆性质”。为了决定新元素应该放在什么位置,它必须和其他元素进行比较,而这个比较就是通过 compareTo 方法来完成的。
    
hashCode()equals() 通常一起重写,以确保两个相等的对象有相同的哈希码。如果对象被放入某些数据结构,如 HashSet 或作为键在 HashMap 中时,Java 会先调用 hashCode() 来确定它们的位置,然后通过 equals() 来判断对象的相等性。尽管 PriorityQueue 本身不使用 hashCode(),但如果你在这些数据结构中存储 Task 对象,hashCode() 将会被调用。

3. ArrayDeque

ArrayDequeDeque 接口的实现类,可以用作双端队列或栈。作为队列时,它比 LinkedList 更加高效。ArrayDeque 使用动态数组来存储元素,能够支持双端的插入和删除操作。

特点:

  • 无大小限制的双端队列,能够从两端插入和删除元素。
1. 作为栈使用(后进先出 - LIFO)

使用 ArrayDeque 可以模拟栈的操作,常见的方法包括:

  • push(E e):将元素压入栈顶。

  • pop():弹出栈顶元素。

  • peek():查看栈顶元素但不移除。

    在这里插入图片描述

import java.util.ArrayDeque;

public class StackExample {
    public static void main(String[] args) {
        ArrayDeque<String> stack = new ArrayDeque<>();

        // 模拟栈操作
        stack.push("Element 1");
        stack.push("Element 2");
        stack.push("Element 3");

        // 查看栈顶元素
        System.out.println("Top of the stack: " + stack.peek());  
        // 输出 "Element 3"
        // 弹出栈顶元素
        System.out.println("Popped: " + stack.pop()); 
        // 输出 "Element 3"
        System.out.println("Popped: " + stack.pop());  
        // 输出 "Element 2"

        // 再次查看栈顶
        System.out.println("Top of the stack: " + stack.peek()); 
        // 输出 "Element 1"
    }
}

2.作为队列使用(先进先出 - FIFO)

offer(E e):将元素添加到队列尾部。

poll():移除并返回队列头部的元素。

peek():查看队列头部的元素但不移除。

代码示例:

import java.util.ArrayDeque;

public class QueueExample {
    public static void main(String[] args) {
        ArrayDeque<String> queue = new ArrayDeque<>();

        // 模拟队列操作
        queue.offer("Element 1");
        queue.offer("Element 2");
        queue.offer("Element 3");

        // 查看队列头部元素
        System.out.println("Front of the queue: " + queue.peek());  
        // 输出 "Element 1"

        // 移除队列头部元素
        System.out.println("Removed: " + queue.poll());  
        // 输出 "Element 1"
        System.out.println("Removed: " + queue.poll()); 
        // 输出 "Element 2"

        // 再次查看队列头部
        System.out.println("Front of the queue: " + queue.peek()); 
        // 输出 "Element 3"
    }
}

3.双端队列操作(简称Deque)

ArrayDeque 允许你在队列的两端进行操作,可以在头部或尾部添加和删除元素。

addFirst(E e) / addLast(E e):在头部或尾部添加元素。

removeFirst() / removeLast():移除并返回头部或尾部的元素。

import java.util.ArrayDeque;

public class DequeExample {
    public static void main(String[] args) {
        ArrayDeque<String> deque = new ArrayDeque<>();

        // 在头部和尾部添加元素
        deque.addFirst("Element 1");
        deque.addLast("Element 2");
        deque.addFirst("Element 0");

        // 输出双端队列的内容
        System.out.println(deque);  
        // 输出 "[Element 0, Element 1, Element 2]"

        // 移除头部和尾部元素
        System.out.println("Removed from head: " + deque.removeFirst());  			// 输出 "Element 0"
        System.out.println("Removed from tail: " + deque.removeLast());  			// 输出 "Element 2"

        // 最终的队列状态
        System.out.println(deque);  // 输出 "[Element 1]"
    }
}

栈操作:push()pop()peek()。

队列操作:offer()poll()peek()。

双端队列操作:addFirst()addLast()removeFirst()removeLast()

四、阻塞队列(Blocking Queue)

常见实现类:
ArrayBlockingQueue
LinkedBlockingQueue
PriorityBlockingQueue
SynchronousQueue
DelayQueue
    
    
常用方法
    put(E e)	将元素 e 插入队列,若队列满则阻塞等待。
    take()	移除并返回队列头部元素,若队列为空则阻塞等待。	阻塞方法
    offer(E e)	尝试将元素 e 插入队列,若队列满则返回 false
1.ArrayBlockingQueue

一个有界的阻塞队列,基于数组实现,按照 FIFO 顺序排列元素。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ArrayBlockingQueueExample {
    public static void main(String[] args) throws InterruptedException {
     BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
 3表示 阻塞队列的容量上限。也就是说,这个 LinkedBlockingQueue 最多只能存储 3 个元素。
        // 添加元素,使用 put 方法会阻塞直到有空间
        blockingQueue.put("Task 1");
        blockingQueue.put("Task 2");
        blockingQueue.put("Task 3");
        // blockingQueue.put("Task 4");  // 会阻塞,直到有空间

        // 查看队列内容
        System.out.println("Queue: " + blockingQueue);

        // 移除元素,使用 take 方法会阻塞直到有元素
        System.out.println("Taken: " + blockingQueue.take());  
        // 移除 "Task 1"
        System.out.println("Taken: " + blockingQueue.take()); 
        // 移除 "Task 2"

        // 添加新的元素
        blockingQueue.put("Task 4");

        // 最终队列内容
        System.out.println("Queue: " + blockingQueue);
    }
}

2.LinkedBlockingQueue

一个基于链表的阻塞队列,可以选择有界或无界。

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class LinkedBlockingQueueExample {
    public static void main(String[] args) throws InterruptedException {
     BlockingQueue<String> blockingQueue = new LinkedBlockingQueue<>(5);

        // 添加元素
        blockingQueue.offer("Task A");
        blockingQueue.offer("Task B");
        blockingQueue.offer("Task C");

        // 查看队列内容
        System.out.println("Queue: " + blockingQueue);

        // 移除元素
        System.out.println("Removed: " + blockingQueue.poll()); 
        // 移除 "Task A"

        // 添加新元素
        blockingQueue.offer("Task D");

        // 最终队列内容
        System.out.println("Queue: " + blockingQueue);
    }
}

3.PriorityBlockingQueue

一个支持优先级排序的无界阻塞队列。

import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class PriorityBlockingQueueExample {
    public static void main(String[] args) throws InterruptedException {
BlockingQueue<Integer> priorityBlockingQueue =newPriorityBlockingQueue<>();

        // 添加元素
        priorityBlockingQueue.put(20);
        priorityBlockingQueue.put(10);
        priorityBlockingQueue.put(30);
        priorityBlockingQueue.put(5);

        // 按优先级顺序移除元素
        while (!priorityBlockingQueue.isEmpty()) {
            System.out.println(priorityBlockingQueue.take());
            // 输出顺序: 5, 10, 20, 30
        }
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2109877.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

『功能项目』账号登陆注册界面UI搭建【27】

打开上一篇26DOTween动态文字的项目&#xff0c; 本章要做的事情是搭建账号登录界面&#xff0c;输入账号及密码存储到本地数据库&#xff0c;本地数据库数据是否可登陆游戏进入游戏场景&#xff0c;如果没有账号可以通过账号注册来进入游戏&#xff0c;之后每次账号输入使用注…

项目日志——框架模块设计实用工具类的设计、实现、测试

文章目录 框架模块设计功能叙述模块划分模块关系图 实用工具类设计实现测试 框架模块设计 功能叙述 日志系统的作用就是将一条消息格式化指定格式的字符串之后&#xff0c;写入到指定位置 这个指定位置就有说法了 标准输出指定文件滚动文件 我们可以写入到其中的一种&…

半天攻略:用ChatGPT快速搞定高质量论文,从选题到完稿一站式指南!

在学术论文的撰写过程中&#xff0c;ChatGPT可以作为一个强大的辅助工具&#xff0c;帮助完成从确定主题到整理参考文献的各个环节。接下来&#xff0c;我们将详细介绍如何利用ChatGPT提升论文写作的效率和质量。 确定论文主题 初步探索&#xff1a;通过ChatGPT探索主题&#…

UAEXpert连接kepserver的OPC服务时,出现BadCertificateHostNamelnvalid报错--解决办法

描述&#xff1a; 虚拟机win10安装kepserver&#xff0c;本机的uaexpert软件连接虚拟机上的OPC UA服务&#xff0c;遇到BadCertificateHostNamelnvalid报错问题 报错信息如下&#xff1a; Error BadCertificateHostNamelnvalidwas returned during CreateSession,press Ignor…

Spring事务和事务传播机制(下)

我们上一篇文章学习了 Transactional 的基本使用。接下来我们学习 Transactional 注解的使用细节。 Transactional 注解当中有下面三个常见属性&#xff1a; 1、rollbackFor&#xff1a;异常回滚属性。指定能够触发事务回滚的异常类型。可以指定多个异常类型 2、IsoIation&…

开学季好物狂欢,这些神仙好物让你开学季事半功倍!

随着秋风送爽&#xff0c;开学季再次悄然而至。对于即将迎接新学期的学生们来说&#xff0c;这不仅仅是一个新起点&#xff0c;也是准备全新装备、挑战更高学习效率的好时机。在这个特殊的时节&#xff0c;我们特别为大家策划了一场“开学季好物狂欢”&#xff0c;精选了一系列…

数字人直播防封技巧升级!头部源码厂商如何实现7*24小时无间断直播?

当前&#xff0c;许多用户在使用数字人直播的过程中都遇到了直播间违规和账号被封两大问题&#xff0c;并因此蒙受了一定的损失。在此背景下&#xff0c;不少有计划引入数字人直播的企业和搭建数字人直播系统的创业者也开始有了犹豫。为了让大家能够更放心地入局&#xff0c;本…

Linux之MySQL日志

前言 数据库就像一个庞大的图书馆&#xff0c;而日志则是记录这个图书馆内每一本书的目录。正如在图书馆中找到特定书籍一样&#xff0c;数据库日志帮助我们追溯数据的变更、定位问题和还原状态。 在MySQL中&#xff0c;日志是非常重要的一个组成部分&#xff0c;它记录了数据…

创客匠人对话:如何让客户主动为你付费?北大教授发售秘籍大公开

老蒋创客圈第65期对话标杆直播连麦&#xff0c;我们邀请到【YD世界人才创造社】平台创始人白钰玮老师。为我们分享“家庭教育赛道如何创新模式&#xff0c;单场发售实现高创收&#xff1f;”&#xff0c;深度剖析如何去提升自己的核心竞争力&#xff1f;如何提升个人影响力&…

引领AI PC浪潮,Arm人工智能创新应用大赛火热报名中

AI PC&#xff0c;即搭载人工智能技术的个人电脑&#xff0c;正成为个人电脑市场的新宠儿。而正在如火如荼进行中的 Arm人工智能创新应用大赛&#xff0c;则为敏锐的开发者探索 AI PC 应用开发掘金之路提供了平台。 点击报名 挑战10万奖金池 AI PC 增长强劲&#xff0c;年出货…

2024跨境旺季营销:多渠道广告覆盖中,哪些平台是首选?

跨境电商的旺季即将来临&#xff0c;对于卖家们来说&#xff0c;如何进行有效的营销推广至关重要。在多渠道广告覆盖的策略下&#xff0c;选择合适的平台成为关键。那么&#xff0c;哪些平台是跨境旺季营销的首选呢&#xff1f; 一、社交媒体平台 1、Instagram 以图片和短视频…

易保全出席人工智能应用场景高峰论坛,发布AI-数据资产管理平台2.0应用成果

2024年9月5日&#xff0c;由上海合作组织国家多功能经贸平台、重庆市科技发展基金会指导&#xff0c;重庆市渝中区商务委员会等相关部门主办、华智未来(重庆)科技有限公司承办&#xff0c;重庆民营经济国际合作商会协办的“智驭未来创想无界人工智能应用场景高峰论坛暨成果发布…

使用 nuxi init 创建全新 Nuxt 项目

title: 使用 nuxi init 创建全新 Nuxt 项目 date: 2024/9/6 updated: 2024/9/6 author: cmdragon excerpt: 摘要:本文介绍了如何使用nuxi init命令创建全新的Nuxt.js项目,包括安装所需环境、命令使用方法、指定模板、强制克隆、启动开发服务器等步骤,并提供了完整的项目初…

DAY87 APP 攻防-安卓逆向篇Smail 语法反编译签名重打包Activity 周期Hook 模块

1、APK 逆向-数据修改-结构&格式 2、APK 逆向-逻辑修改-Smail 语法 3、APK 逆向-视图修改-Activity&Xml #章节点&#xff1a; 1、APP 资产-内在提取&外在抓包 2、APP 逆向-反编译&删验证&重打包 3、APP 安全-存储&服务&组件&注册等 演示案例&a…

RasberryPi 3B树莓派基本配置

RaspberryPi 3B树莓派基本配置 文章目录 RaspberryPi 3B树莓派基本配置一、准备工作1.1 硬件准备&#xff1a;1.1.1 树莓派和电源适配器&#xff1a;1.1.2 USB转TTL模块&#xff1a;1.1.3 读卡器和TF卡&#xff1a; 1.2 软件准备&#xff1a;1.2.1 下载 Raspberry Pi OS&#x…

SpringMvc后续3

返回值问题 ModelAndView返回 字符串返回 转发和重定向 默认返回页面是转发效果 如果需要重定向&#xff0c;在返回页面的时候&#xff0c;追加redirect:&#xff0c;后边需要追加视图后缀 Ajax返回 控制层 jsp文件 导入json包 Session问题

案例-上海某科技公司:监控易7.0重塑服务器监控模式

在上海这座充满创新与活力的城市中&#xff0c;科技型企业如雨后春笋般涌现&#xff0c;而上海某科技发展有限公司&#xff08;以下简称“该公司”&#xff09;便是其中的佼佼者。随着业务的蓬勃发展和IT环境的日益复杂&#xff0c;服务器作为业务运行的核心&#xff0c;其稳定…

2024全国大学省数学建模竞赛A题-原创参考论文(部分+第一问代码)

一问题重述 1.1 问题背景 "板凳龙"&#xff0c;又称"盘龙"&#xff0c;是浙闽地区的传统地方民俗文化活动。这种独特的表演艺术形式融合了中国传统龙舞的精髓和地方特色&#xff0c;展现了人们对美好生活的向往和对传统文化的传承。 在板凳龙表演中&am…

批量文件编码转换用python实现的utf8转gb2312,vscode设置特殊文件的默认打开编码

批量文件编码转换用python实现的utf8转gb2312, 任意编码之间的相互转换都是可以的.改一下下面的参数即可 convert.py文件内容如下 import os import glob import chardet#检测文件编码类型 def detect_file_encoding(file_path):with open(file_path, rb) as f:data f.read(…

InternVL-2B尝试

以最新的官方文档为准&#xff1a;https://internvl.readthedocs.io/en/latest/get_started/installation.html 一、环境配置 a. 下载InternVL完整的repo&#xff08;无权重&#xff0c;空间占的不大&#xff09; git clone https://github.com/OpenGVLab/InternVL.git b. …