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

embedded/2024/11/14 22:42:22/

目录

  • 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/embedded/137611.html

相关文章

leetcode61:旋转链表

给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], k 2 输出&#xff1a;[4,5,1,2,3]示例 2&#xff1a; 输入&#xff1a;head [0,1,2], k 4 输出&#xff1a;[2,0,1…

第四十五章 Vue之Vuex模块化创建(module)

目录 一、引言 二、模块化拆分创建方式 三、模块化拆分完整代码 3.1. index.js 3.2. module1.js 3.3. module2.js 3.4. module3.js 3.5. main.js 3.6. App.vue 3.7. Son1.vue 3.8. Son2.vue 四、访问模块module的state ​五、访问模块中的getters ​六、mutati…

React Native 全栈开发实战班 -React Native 基础

本课程旨在帮助学员系统掌握 React Native 全栈开发技能&#xff0c;从基础入门到实战项目开发。课程将分为多个模块&#xff0c;第一部分将聚焦于 React Native 的基础知识&#xff0c;包括开发环境搭建、React Native 简介与特点&#xff0c;以及项目结构解析。 第一部分&am…

Hbase小测

一. 单选题&#xff08;共 8 题&#xff0c;16.0 分&#xff09; 1. (单选题, 2.0 分) Hbase等NoSQL数据库采用下面____设计原则 A. APB. CAC. CP 正确答案: C 2. (单选题, 2.0 分) 关于BASE&#xff0c;下面说法错误的是 A. 隔离性B. 软状态C. 基本可用D. 最终一致性 正…

【C++课程学习】:继承:默认成员函数

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;C课程学习 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 构造函数 &#x1f369;默认构造函数&#xff08;这里指的是编译器生成的构造函数&#xff09;&#…

【Qt-ROS开发】使用 Qt Creator 构建和编译含 ROS 库的 Qt 项目

【Qt-ROS】使用 Qt Creator 构建和编译含 ROS 库的项目 网上大多数办法是在 Qt creator中安装 ros_qtc_plugin 插件&#xff0c;项目以 ROS1 工作空间的形式构建&#xff0c;还是使用 catkin 来构建整个项目。但是这种方式局限很大&#xff0c;导入 Qt 的组件反而变得很麻烦&a…

机器情绪及抑郁症算法

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月12日17点02分 点击开启你的论文编程之旅https://www.aspiringcode.com/content?id17230869054974 计算机来理解你的情绪&a…

python+pptx:(三)添加统计图、删除指定页

目录 统计图 删除PPT页 from pptx import Presentation from pptx.util import Cm, Inches, Mm, Pt from pptx.dml.color import RGBColor from pptx.chart.data import ChartData from pptx.enum.chart import XL_CHART_TYPE, XL_LABEL_POSITION, XL_DATA_LABEL_POSITIONfil…