Java集合Queue——针对实习面试

news/2024/11/16 3:59:46/

目录

  • Java集合Queue
    • Queue接口的特点是什么?
    • Queue和Deque的区别?
    • ArrayDeque和LinkedList的区别?
    • 什么是PriorityQueue?
    • 什么是BlockingQueue?

Java集合Queue

在这里插入图片描述

Queue接口的特点是什么?

Queue接口在Java中是一个特殊的集合,它具有以下特点:

  1. 先进先出(FIFO)原则
    Queue接口遵循FIFO(先进先出)的原则,这意味着元素被添加到队列的末尾,并从队列的前端移除。

  2. 元素访问
    Queue提供了对队列头部和尾部元素的访问。peek()方法允许查看队列头部的元素而不移除它,而element()方法也用于获取队头元素,但与peek()不同,如果队列为空,element()会抛出NoSuchElementException异常。

  3. 添加和移除元素
    Queue接口提供了add(E e)remove()方法来添加和移除元素,这些方法在队列满或空时会抛出异常。为了更安全地处理这些情况,Queue还提供了offer(E e)poll()方法,它们在无法添加或移除元素时返回falsenull,而不是抛出异常。

  4. 容量限制
    某些Queue实现(如ArrayDequeLinkedBlockingQueue)有容量限制,而其他实现(如LinkedList)则没有容量限制。

  5. 双端队列(Deque)
    Queue可以扩展为Deque接口,这允许元素从队列的两端进行插入和移除操作,使得Queue既可以作为队列使用,也可以作为栈使用。

  6. 线程安全性
    Queue接口本身不提供线程安全的保证,但Java提供了BlockingQueue接口,它是Queue的子接口,提供了线程安全的队列实现,适用于多线程环境。

  7. 泛型支持
    Queue接口支持泛型,这意味着你可以指定队列中元素的类型,从而在编译时期提供类型安全。

  8. 优先级队列
    Queue的一个子接口PriorityQueue提供了优先级队列的实现,元素根据其自然顺序或通过提供的Comparator进行排序。

  9. 非阻塞和阻塞操作
    对于非阻塞操作,Queue提供了poll()offer()方法;对于阻塞操作,BlockingQueue提供了take()put()方法,这些方法在无法进行操作时会阻塞调用线程。

了解Queue接口的这些特点对于在Java中正确使用队列至关重要,无论是在单线程还是多线程环境中。

Queue和Deque的区别?

QueueDeque都是Java集合框架中的接口,它们都可以用来存储元素,但它们之间存在一些关键的区别:

  1. 顺序不同

    • Queue接口是先进先出(FIFO)的数据结构,元素从队尾添加,从队头移除。
    • Deque接口是双端队列,支持从两端添加和移除元素,既可以实现FIFO(队列)的行为,也可以实现后进先出(LIFO,即栈)的行为。
  2. 方法不同

    • Queue提供了add, offer, remove, poll, element, peek等方法。
    • Deque除了包含Queue的所有方法外,还提供了addFirst, addLast, offerFirst, offerLast, pollFirst, pollLast, removeFirst, removeLast, getFirst, getLast, peekFirst, peekLast等方法,这些方法允许从两端进行操作。
  3. 行为不同

    • Queue的行为更受限,只能从队头移除元素,从队尾添加元素。
    • Deque的行为更灵活,可以作为队列、栈或两者的组合来使用。
  4. 实现类不同

    • Queue的常见实现类有LinkedList, PriorityQueue, ArrayDeque(也是Deque的实现)。
    • Deque的常见实现类有ArrayDequeLinkedList
  5. 性能考虑

    • 对于QueueLinkedList是一个常见的选择,因为它允许快速的插入和删

ArrayDeque和LinkedList的区别?

ArrayDequeLinkedList都是Java中的双端队列(Deque)实现,但它们在内部数据结构和性能特性上有所不同。以下是它们的主要区别:

  1. 内部数据结构

    • ArrayDeque是基于动态数组实现的,这意味着它使用一个可扩展的数组来存储元素。
    • LinkedList是基于双向链表实现的,每个元素都包含对前一个和后一个元素的引用。
  2. 随机访问性能

    • ArrayDeque支持快速的随机访问,因为它的元素存储在数组中,可以通过索引直接访问。
    • LinkedList不支持快速随机访问,因为它需要从头或尾开始遍历链表才能到达特定位置。
  3. 内存占用

    • ArrayDeque的内存占用通常比LinkedList少,因为它不需要为每个元素存储额外的前驱和后继指针。
    • LinkedList的每个节点都需要额外的空间来存储两个指针(指向前一个和后一个元素),这增加了内存开销。
  4. 扩容操作

    • ArrayDeque在需要时会进行扩容操作,这涉及到创建一个新的数组并复制旧数组中的元素,这是一个相对昂贵的操作,但通常比链表操作快。
    • LinkedList不需要扩容操作,因为它总是能够通过创建新的节点来动态地添加元素。
  5. 插入和删除性能

    • ArrayDeque在两端的插入和删除操作上通常比LinkedList快,因为它不需要像链表那样维护前后节点的链接。
    • LinkedList在两端的插入和删除操作上也很快,因为它只需要改变几个节点的指针,但随机位置的插入和删除操作会慢一些。
  6. 线程安全性

    • 两者都不是线程安全的,但可以通过Collections.synchronizedDeque方法来创建线程安全的ArrayDequeLinkedList
  7. 使用场景

    • ArrayDeque适合于需要快速随机访问元素的场景,以及作为栈或队列使用时,元素数量相对固定的情况。
    • LinkedList适合于需要在列表中间频繁插入和删除元素的场景,或者作为队列使用时,元素数量频繁变化的情况。
  8. 实现的接口

    • ArrayDeque实现了Deque接口和Queue接口。
    • LinkedList实现了List接口、Deque接口和Queue接口。
  9. 性能特性

    • ArrayDeque在并发环境下的性能通常优于LinkedList,因为它的扩容操作和随机访问操作更快。

在选择ArrayDequeLinkedList时,需要根据具体的应用场景和性能要求来决定使用哪一个。如果需要频繁的随机访问,或者队列的大小相对固定,ArrayDeque可能是更好的选择。如果需要在列表中间频繁地进行插入和删除操作,或者队列的大小频繁变化,LinkedList可能更合适。

什么是PriorityQueue?

PriorityQueue是Java中的一个类,它实现了Queue接口,并且是java.util包的一部分。以下是PriorityQueue的一些关键特性:

  1. 排序

    • PriorityQueue是一个优先级队列,其中元素根据它们的自然顺序或者通过提供的Comparator进行排序。队列的头部(队首)总是队列中具有最高优先级的元素。
  2. 无界队列

    • 默认情况下,PriorityQueue是一个无界队列,这意味着它可以无限增长,除非内存不足。
  3. 线程不安全

    • PriorityQueue不是线程安全的。如果需要线程安全的优先级队列,可以使用PriorityBlockingQueue
  4. 元素唯一性

    • PriorityQueue不允许插入null元素,并且根据使用的比较器(Comparator),可能也不支持元素重复。
  5. 插入和删除操作

    • PriorityQueue提供了offer(E e)方法来添加元素,和poll()方法来移除并返回队列头部的元素。这些操作的时间复杂度是O(log(n))
  6. 元素访问

    • 可以通过peek()方法来查看但不移除队列头部的元素,如果队列为空,则返回null
  7. 自定义排序

    • 在创建PriorityQueue实例时,可以提供一个Comparator来定义元素的排序规则。
  8. 迭代器

    • PriorityQueue提供了一个迭代器,允许按优先级顺序遍历队列中的元素。
  9. 堆的实现

    • PriorityQueue通常使用堆数据结构(通常是二叉堆)来存储元素,以保证高效的插入和删除操作。
  10. 使用场景

    • PriorityQueue适用于需要根据优先级处理元素的场景,例如任务调度、事件驱动模拟等。

下面是一个简单的PriorityQueue使用示例:

java">import java.util.PriorityQueue;public class PriorityQueueExample {public static void main(String[] args) {PriorityQueue<Integer> pq = new PriorityQueue<>(); // 默认自然顺序排序pq.offer(3);pq.offer(1);pq.offer(2);System.out.println(pq.poll()); // 输出 1System.out.println(pq.poll()); // 输出 2System.out.println(pq.poll()); // 输出 3}
}

在这个例子中,整数被添加到优先级队列中,并按照自然顺序(升序)排序。使用poll()方法可以按优先级顺序移除元素。

什么是BlockingQueue?

BlockingQueue是Java并发包java.util.concurrent中的一个接口,它继承自java.util.Queue接口。BlockingQueue提供了线程安全的队列实现,主要用于多线程之间的数据交换。以下是BlockingQueue的一些关键特性:

  1. 线程安全

    • BlockingQueue的所有实现都是线程安全的,这意味着它们可以被多个线程安全地访问而不需要额外的同步。
  2. 阻塞操作

    • BlockingQueue提供了阻塞的插入(put)和移除(take)操作。当队列满时,插入操作会阻塞,直到队列中有空间;当队列空时,移除操作会阻塞,直到队列中有元素。
  3. 可选的公平性

    • 一些BlockingQueue实现(如LinkedBlockingQueue)允许构造函数中指定公平性(fairness)。如果设置为公平性模式,线程将根据它们等待的时间来访问队列,而不公平的队列可能允许饥饿现象发生。
  4. 容量限制

    • 某些BlockingQueue实现(如ArrayBlockingQueueLinkedBlockingQueue)有固定容量,而其他实现(如LinkedBlockingQueue的无界版本)可以有无限容量。
  5. 非阻塞操作

    • 除了阻塞操作外,BlockingQueue还提供了非阻塞的插入(offer)和移除(poll)操作,这些操作在无法立即完成时会立即返回。
  6. 支持超时

    • BlockingQueue提供了带有超时的插入(offer(E e, long timeout, TimeUnit unit))和移除(poll(long timeout, TimeUnit unit))操作,允许线程在等待一定时间后放弃。
  7. 支持中断

    • BlockingQueue的阻塞操作可以通过中断来响应中断信号,允许线程在等待时响应中断,提高程序的响应性。
  8. 常见实现

    • ArrayBlockingQueue:一个由数组支持的有界阻塞队列。
    • LinkedBlockingQueue:一个由链表支持的可选有界阻塞队列。
    • PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
    • SynchronousQueue:一个不存储元素的阻塞队列,每个插入操作必须等待一个移除操作,反之亦然。
  9. 使用场景

    • BlockingQueue适用于生产者-消费者问题,其中生产者线程将元素放入队列,消费者线程从队列中取出元素。

下面是一个简单的BlockingQueue使用示例:

java">import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;public class BlockingQueueExample {public static void main(String[] args) throws InterruptedException {BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();// 生产者线程Thread producer = new Thread(() -> {try {queue.put(1); // 将元素放入队列System.out.println("Produced: 1");} catch (InterruptedException e) {Thread.currentThread().interrupt();}});// 消费者线程Thread consumer = new Thread(() -> {try {int element = queue.take(); // 从队列中取出元素System.out.println("Consumed: " + element);} catch (InterruptedException e) {Thread.currentThread().interrupt();}});producer.start();consumer.start();producer.join();consumer.join();}
}

在这个例子中,生产者线程将一个元素放入LinkedBlockingQueue,而消费者线程从队列中取出该元素。如果队列为空,take方法将阻塞消费者线程,直到队列中有元素可用。


http://www.ppmy.cn/news/1547342.html

相关文章

51c自动驾驶~合集25

我自己的原文哦~ https://blog.51cto.com/whaosoft/11952510 #AllWeather-Net 拿捏所有天气&#xff01;增强所有恶劣环境图像~ 论文题目&#xff1a;AllWeather-Net: Unified Image Enhancement for Autonomous Driving Under Adverse Weather and Low-Light Conditions 论文…

探秘Spring Boot中的@Conditional注解

文章目录 1. 什么是Conditional注解&#xff1f;2. 为什么需要Conditional注解&#xff1f;3. 如何使用Conditional注解&#xff1f;4. Conditional注解的高级用法5. 注意事项6. 结语推荐阅读文章 在Spring Boot的世界里&#xff0c;配置的灵活性和多样性是至关重要的。有时候&…

个人C++复习知识点(1)

在 C 中&#xff0c;函数重载是指在同一个作用域中定义多个同名函数&#xff0c;这些函数通过参数的类型、数量或顺序的不同来区分。函数参数的顺序确实可以作为重载的条件之一。 函数重载的原则 C 允许通过以下几种方式来重载函数&#xff1a; 参数类型不同&#xff1a;函数…

D64【python 接口自动化学习】- python基础之数据库

day64 SQL-DQL-基础查询 学习日期&#xff1a;20241110 学习目标&#xff1a;MySQL数据库-- 133 SQL-DQL-基础查询 学习笔记&#xff1a; 基础数据查询 基础数据查询-过滤 总结 基础查询的语法&#xff1a;select 字段列表|* from 表过滤查询的语法&#xff1a;select 字段…

HarmonyOS Next星河版笔记--界面开发(4)

布局 1.1.线性布局 线性布局通过线性容器column和row创建 column容器&#xff1a;子元素垂直方向排列row容器&#xff1a;子元素水平方向排列 1.1.1.排布主方向上的对齐方式&#xff08;主轴&#xff09; 属性&#xff1a;.justifyContent&#xff08;枚举FlexAlign&#…

大模型在蓝鲸运维体系应用——蓝鲸运维开发智能助手

本文来自腾讯蓝鲸智云社区用户: CanWay 背景 1、运维转型背景 蓝鲸平台从诞生之初&#xff0c;就一直在不遗余力地推动运维转型&#xff0c;让运维团队可以通过一体化PaaS平台&#xff0c;快速编写脚本&#xff0c;编排流程&#xff0c;开发运维工具&#xff0c;从被动地提供…

将答题成绩排行榜数据通过前端生成excel的方式实现导出下载功能

需求是这样的&#xff0c;在答题活动结束后&#xff0c;主办方想要导出排行榜成绩到excel&#xff0c;并能够在小程序里面打开查看、转发或下载保存到本地的功能。 我的实现思路大概是这样&#xff0c;先把排行榜数据按照得分排名顺序&#xff0c;处理成对应的JSON数据结构&…

【机器学习】如何配置anaconda环境(无脑版)

马上就要上机器学习的实验&#xff0c;这里想写一下我配置机器学习的anaconda环境的二三事 一、首先&#xff0c;下载安装包&#xff1a; Download Now | Anaconda 二、打开安装包&#xff0c;一直点NEXT进行安装 这里要记住你要下载安装的路径在哪&#xff0c;后续配置环境…