Java 入门指南:Queue 接口

news2025/1/13 17:32:42

Collection 接口

Collection 接口提供了一系列用于操作和管理集合的方法,包括添加、删除、查询、遍历等。它是所有集合类的根接口,包括 ListSetQueue 等。

![[Collection UML.png]]

Collection 接口常见方法

  • add(E element):向集合中添加元素。

  • addAll(Collection col):将 col 中的所有元素添加到集合中

  • boolean remove(Object obj):通过元素的equals方法判断是否是要删除的那个元素,只删除找到的第一个元素

  • boolean removeAll(Collection col):取两集合差集

  • boolean retain(Collection col):把交集的结果存在当前的集合中,不影响col

  • boolean contains(Object obj):判断集合中是否包含指定的元素。

  • boolean containsAll(Collection col):调用元素的equals方法来比较的。用两个两个集合的元素逐一比较

  • size():返回集合中的元素个数。

  • isEmpty():判断集合是否为空。

  • clear():清空集合中的所有元素。

  • iterator():返回用于遍历集合的迭代器。

  • hashCode(): 获取集合对象的哈希值

  • Object[] toArray():转换成对象数组

Queue 接口

队列(Queue)是一种常见的数据结构,它遵循 先进先出 FIFO 的原则。Java提供了一个 Queue 接口,它是 Collection 接口的子接口,定义了一些特定于队列数据结构的方法。

Queue 接口的实现一般会提供不同的方法来处理容量限制、是否插入成功等问题,具体的使用可以根据实现类的特点来选择适合的方法。

Queue 常用方法

以下是 Queue 接口中常用的一些方法:

  1. add(E element):将指定的元素添加到队列的尾部。如果队列已满,则抛出一个异常。

  2. offer(E element):将指定的元素添加到队列的尾部。如果队列已满,则返回false,否则返回true。

  3. remove():移除并返回队列头部的元素。如果队列为空,则抛出一个异常。

  4. poll():移除并返回队列头部的元素。如果队列为空,则返回null。

  5. element():返回队列头部的元素,但不移除。如果队列为空,则抛出一个异常。

  6. peek():返回队列头部的元素,但不移除。如果队列为空,则返回null。

Queue 实现类

Queue 接口有几种常见的实现类,包括 ArrayQueue(自定义实现)、LinkedListArrayDequePriorityQueue 等。

  • ArrayQueue:基于数组实现的队列,访问和移除队首元素较快,但可能需要在队列满或半空时进行数组的复制操作。

  • LinkedListQueue:基于双向链表实现的队列,添加和移除元素非常快,因为只需要更新指针即可。

  • PriorityQueue:基于小顶堆实现的队列,队列中的元素会自动排序,最小的元素位于队首。适合需要优先级排序的场景。

  • ArrayDeque:基于数组实现的双端队列,可以作为队列或栈使用。两端的插入和移除操作都非常快,因为只需要更新指针即可。

根据具体的应用场景选择合适的队列类型非常重要。例如:

  • 如果需要优先级排序的队列,可以选择 PriorityQueue

  • 如果需要高效的两端操作,可以选择 ArrayDeque

  • 如果需要简单快速的队列操作,可以选择 ArrayQueueLinkedListQueue

ArrayQueue
  • ArrayQueue 使用数组(如 Object[] 或泛型数组 T[])来存储队列中的元素。

  • 由于数组的大小是固定的,因此 ArrayQueue 需要一种机制来处理队列的扩容,当元素数量超过数组容量时,能够动态地增加数组的大小。

  • 为了避免在数组前端添加元素时导致的大量元素移动(即“假溢出”问题),ArrayQueue 可能会使用循环数组(也称为环形队列)的实现方式。

ArrayQueue 扩容机制

ArrayQueue 中,扩容通常发生在以下两种情况:

  1. 队列已满:当队列中的元素数量达到数组的最大容量时。
  2. 队列半空:当队列中的元素数量减少到一定比例时,为了节省内存空间。

ArrayQueue 的扩容机制是动态的,可以根据需要自动增加或减少容量。这种机制使得 ArrayQueue 能够有效地管理内存,并且在大多数情况下提供了良好的性能。ArrayQueue 会采取两种扩容策略:

  1. 默认扩容比例:通常情况下,ArrayQueue 会在队列满时将容量扩大为原来的两倍。

  2. 缩容策略:当队列中的元素数量减少到一定程度时,比如减少到最大容量的四分之一,ArrayQueue 可能会将容量减小到一半。

下面通过代码示例来说明 ArrayQueue 的扩容过程:

import java.util.NoSuchElementException;

public class ArrayQueue<T> {
    private T[] elements;
    private int head;
    private int tail;
    private int size;

    public ArrayQueue(int capacity) {
        elements = (T[]) new Object[capacity];
        head = 0;
        tail = 0;
        size = 0;
    }

    public void enqueue(T element) {
        if (size == elements.length) {
            resize(elements.length * 2);  // 扩容为原来的两倍
        }
        elements[tail] = element;
        tail = (tail + 1) % elements.length;
        size++;
    }

    public T dequeue() {
        if (isEmpty()) {
            throw new NoSuchElementException("Queue is empty.");
        }
        T removedElement = elements[head];
        elements[head] = null; // 帮助垃圾回收
        head = (head + 1) % elements.length;
        size--;
        if (size > 0 && size == elements.length / 4) {
            resize(elements.length / 2);  // 缩容为原来的一半
        }
        return removedElement;
    }

    private void resize(int newCapacity) {
        T[] newElements = (T[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newElements[i] = elements[(i + head) % elements.length];
        }
        elements = newElements;
        head = 0;
        tail = size;
    }

    // 其他方法省略
}

代码解析:

  1. enqueue 方法:当尝试添加新元素时,如果队列已满(size == elements.length),则调用 resize 方法进行扩容。

  2. resize 方法:在 resize 方法中,创建一个新的数组,并将旧数组中的元素复制到新数组中。新数组的大小取决于扩容还是缩容的情况。

  3. dequeue 方法:当队列中的元素数量减少到最大容量的四分之一时,ArrayQueue 会调用 resize 方法进行缩容。

ArrayQueue 使用示例
import java.util.NoSuchElementException;

public class ArrayQueueExample {
    public static void main(String[] args) {
        // 创建一个 ArrayQueue
        ArrayQueue<Integer> queue = new ArrayQueue<>(10);

        // 添加元素
        queue.enqueue(1);
        queue.enqueue(2);
        queue.enqueue(3);

        // 访问队首元素
        System.out.println("Peek: " + queue.peek());  // 输出: Peek: 1

        // 移除队首元素
        System.out.println("Dequeued: " + queue.dequeue());  // 输出: Dequeued: 1

        // 再次访问队首元素
        System.out.println("New peek: " + queue.peek());  // 输出: New peek: 2

        // 检查队列是否为空
        System.out.println("Is the queue empty? " + queue.isEmpty());  // 输出: Is the queue empty? false

        // 获取队列的大小
        System.out.println("Size of the queue: " + queue.size());  // 输出: Size of the queue: 2

        // 遍历队列中的所有元素
        while (!queue.isEmpty()) {
            System.out.println(queue.dequeue());  // 依次输出: 2, 3
        }
    }
}
LinkedListQueue

LinkedListQueue(基于链表 LinkedList)内部使用双向链表来存储元素。每个节点包含数据部分、指向前一个节点的指针(prev)和指向后一个节点的指针(next)。这种结构使得在链表的两端添加或删除元素时,操作的时间复杂度为O(1)。

特点
  • 线程安全性LinkedList 不是线程安全的,如果多个线程同时访问一个 LinkedList 实例,并且至少有一个线程从结构上修改了列表,那么它必须保持外部同步。

  • 容量:由于LinkedList 是基于链表的,它不需要在创建时指定容量,并且可以根据需要动态地增长和缩小。

  • 灵活性LinkedList 不仅可以用作队列,还可以用作栈、双端队列等,因为它实现了 Deque 接口。

  • 当需要频繁地在集合的两端进行添加或删除操作时;或当集合的大小经常变化,且不需要随机访问元素时,LinkedList 是一个很好的选择。

LinkedListQueue 使用示例
public class LinkedListQueueExample {
    public static void main(String[] args) {
        // 创建一个 LinkedListQueue
        LinkedListQueue<Integer> queue = new LinkedListQueue<>();

        // 添加元素
        queue.enqueue(1);
        queue.enqueue(2);
        queue.enqueue(3);

        // 访问队首元素
        System.out.println("Peek: " + queue.peek());  // 输出: Peek: 1

        // 移除队首元素
        System.out.println("Dequeued: " + queue.dequeue());  // 输出: Dequeued: 1

        // 再次访问队首元素
        System.out.println("New peek: " + queue.peek());  // 输出: New peek: 2

        // 检查队列是否为空
        System.out.println("Is the queue empty? " + queue.isEmpty());  // 输出: Is the queue empty? false

        // 获取队列的大小
        System.out.println("Size of the queue: " + queue.size());  // 输出: Size of the queue: 2

        // 遍历队列中的所有元素
        while (!queue.isEmpty()) {
            System.out.println(queue.dequeue());  // 依次输出: 2, 3
        }
    }
}
PriorityQueue

PriorityQueue 是一个基于优先级堆的无界优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时所提供的 Comparator 进行排序,具体取决于所使用的构造方法。

构造方法
  1. 创建一个初始容量为 11 的空优先级队列,元素将按照自然顺序进行排序。
PriorityQueue()
  1. 创建一个指定初始容量的空优先级队列,元素将按照自然顺序进行排序。
PriorityQueue(int initialCapacity)
  1. 创建一个指定初始容量和自定义比较器的空优先级队列,根据比较器进行元素排序。
PriorityQueue(int Capacity, Comparator<? super E> comparator)
  1. 创建一个包含指定集合元素的优先级队列,元素将按照自然顺序进行排序。
PriorityQueue(Collection<? extends E> collection)
  1. 创建一个包含指定优先级队列所有元素的新优先级队列,元素将按照自然顺序进行排序。
PriorityQueue(PriorityQueue<? extends E> queue)
  1. 创建一个包含指定排序集合元素的优先级队列,元素将按照集合的顺序进行排序。
PriorityQueue(SortedSet<? extends E> set)
特点
  1. 优先级:PriorityQueue 中的元素可以使用自然排序或通过 Comparator 进行自定义排序,队列会根据元素的优先级将它们插入到合适的位置。如果多个元素具有相同的优先级,则它们之间是没有顺序保证的。

  2. 不允许 null 元素:PriorityQueue 不允许插入 null 元素。

  3. 队列容量:PriorityQueue 的容量可以是固定的,也可以是动态扩展的(默认为 11)。

  4. 不保证插入顺序:PriorityQueue 不保证插入的顺序,只保证出队顺序为优先级高的元素先出队

  5. 队列的头部是按指定排序方式确定的最小元素(队列中的最小元素总是位于队列的头部)。当元素被添加或移除时,队列会自动重新排序以保持最小元素在前的性质

PriorityQueue 使用示例
import java.util.PriorityQueue;

public class PriorityQueueExample {
    public static void main(String[] args) {
        // 创建一个 PriorityQueue
        PriorityQueue<Integer> queue = new PriorityQueue<>();

        // 添加元素
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);
        queue.offer(4);
        queue.offer(5);

        // 移除队首元素(最小值)
        System.out.println("Removed: " + queue.poll());  // 输出: Removed: 1

        // 访问队首元素(最小值)
        System.out.println("Peek: " + queue.peek());  // 输出: Peek: 2

        // 再次移除队首元素
        System.out.println("Removed: " + queue.poll());  // 输出: Removed: 2

        // 检查队列是否为空
        System.out.println("Is the queue empty? " + queue.isEmpty());  // 输出: Is the queue empty? false

        // 获取队列的大小
        System.out.println("Size of the queue: " + queue.size());  // 输出: Size of the queue: 3

        // 遍历队列中的所有元素
        while (!queue.isEmpty()) {
            System.out.println(queue.poll());  // 依次输出: 3, 4, 5
        }
    }
}
PriorityQueue 自定义比较

如果需要根据自定义的规则对元素进行排序,可以提供一个 Comparator 对象给 PriorityQueue 的构造函数。下面是一个示例,展示了如何根据整数的绝对值对元素进行排序:

import java.util.Comparator;
import java.util.PriorityQueue;

public class CustomPriorityQueueExample {
    public static void main(String[] args) {
        // 创建一个 PriorityQueue 并提供自定义的 Comparator
        PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Math.abs(o1) - Math.abs(o2);
            }
        });

        // 添加元素
        queue.offer(-10);
        queue.offer(5);
        queue.offer(15);
        queue.offer(1);

        // 访问队首元素
        System.out.println("Peek: " + queue.peek());  // 输出: Peek: 1

        // 移除队首元素
        System.out.println("Removed: " + queue.poll());  // 输出: Removed: 1

        // 再次访问队首元素
        System.out.println("New peek: " + queue.peek());  // 输出: New peek: 5

        // 获取队列的大小
        System.out.println("Size of the queue: " + queue.size());  // 输出: Size of the queue: 3

        // 遍历队列中的所有元素
        while (!queue.isEmpty()) {
            System.out.println(queue.poll());  // 依次输出: 5, -10, 15
        }
    }
}
Deque 接口

Deque(双端队列)是一种特殊的队列数据结构,它允许在队列的两端进行元素的插入和移除操作。Java 提供了一个 Deque 接口,它是 Queue 接口的子接口,并扩展了 Queue 中定义的方法。

Deque 接口既可以作为队列使用,也可以作为栈使用。它提供了常见的队列和栈操作的方法,例如添加元素、移除元素、获取元素等。具体的使用方式取决于我们如何使用这些方法来实现我们的需求。

常用方法
  1. addFirst(E element):将指定的元素插入到双端队列的头部。如果插入操作成功,则将返回 true;否则,将抛出异常。

  2. addLast(E element):将指定的元素插入到双端队列的尾部。如果插入操作成功,则将返回 true;否则,将抛出异常。

  3. offerFirst(E element):将指定的元素插入到双端队列的头部。如果插入操作成功,则将返回 true;否则,将返回 false。

  4. offerLast(E element):将指定的元素插入到双端队列的尾部。如果插入操作成功,则将返回 true;否则,将返回 false。

  5. removeFirst():移除并返回双端队列的头部元素。如果队列为空,则将抛出异常。

  6. removeLast():移除并返回双端队列的尾部元素。如果队列为空,则将抛出异常。

  7. pollFirst():移除并返回双端队列的头部元素。如果队列为空,则返回 null。

  8. pollLast():移除并返回双端队列的尾部元素。如果队列为空,则返回 null。

  9. getFirst():返回双端队列的头部元素,但不会移除它。如果队列为空,则将抛出异常。

  10. getLast():返回双端队列的尾部元素,但不会移除它。如果队列为空,则将抛出异常。

  11. peekFirst():返回双端队列的头部元素,但不会移除它。如果队列为空,则返回 null。

  12. peekLast():返回双端队列的尾部元素,但不会移除它。如果队列为空,则返回 null。

Deque 使用示例 (使用 ArrayDeque)
import java.util.ArrayDeque;
import java.util.Deque;

public class DequeExample {
    public static void main(String[] args) {
        // 创建一个 Deque (使用 ArrayDeque)
        Deque<Integer> deque = new ArrayDeque<>();

        // 添加元素
        deque.offerFirst(1);
        deque.offerLast(2);
        deque.offerLast(3);

        // 访问队首元素
        System.out.println("First element: " + deque.peekFirst());  // 输出: First element: 1

        // 访问队尾元素
        System.out.println("Last element: " + deque.peekLast());  // 输出: Last element: 3

        // 移除队首元素
        System.out.println("Removed first: " + deque.pollFirst());  // 输出: Removed first: 1

        // 再次访问队首元素
        System.out.println("New first element: " + deque.peekFirst());  // 输出: New first element: 2

        // 检查队列是否为空
        System.out.println("Is the deque empty? " + deque.isEmpty());  // 输出: Is the deque empty? false

        // 获取队列的大小
        System.out.println("Size of the deque: " + deque.size());  // 输出: Size of the deque: 2

        // 遍历队列中的所有元素
        while (!deque.isEmpty()) {
            System.out.println(deque.pollFirst());  // 依次输出: 2, 3
        }
    }
}

总结

Queue 接口是Java集合框架中的一个重要组成部分,它定义了一种先进先出(FIFO, First-In-First-Out)的数据结构,用于存储和管理元素。Queue 接口继承自 Collection 接口,并提供了一系列方法来支持队列的基本操作,如添加元素、移除元素和检查队列的状态。

队列的一个关键特性是只能在一端添加元素(队尾),而在另一端移除元素(队首)。Queue 接口有多种实现类,包括 LinkedListArrayDequePriorityQueue 等,每种实现都有其特定的用途和性能特点。

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

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

相关文章

大模型笔记之-XTuner微调个人小助手认知

前言 使用XTuner 微调个人小助手认知 一、下载模型 #安装魔搭依赖包 pip install modelscope新建download.py内容如下 其中Shanghai_AI_Laboratory/internlm2-chat-1_8b是魔搭对应的模型ID cache_dir/home/aistudio/data/model’为指定下载到本地的目录 from modelscope im…

Stable Diffusion的微调方法原理总结

目录 1、Textural Inversion&#xff08;简易&#xff09; 2、DreamBooth&#xff08;完整&#xff09; 3、LoRA&#xff08;灵巧&#xff09; 4、ControlNet&#xff08;彻底&#xff09; 5、其他 1、Textural Inversion&#xff08;简易&#xff09; 不改变网络结构&…

Ciallo~(∠・ω・ )⌒☆第二十五篇 Redis

Redis 是一个高性能的键值存储数据库&#xff0c;它能够在内存中快速读写数据&#xff0c;并且支持持久化到磁盘。它被广泛应用于缓存、队列、实时分析等场景。 一、启动redis服务器 要打开redis服务器&#xff0c;需要在终端中输入redis-server命令。确保已经安装了redis&…

【Java】/* 链式队列 和 循环队列 - 底层实现 */

一、链式队列 1. 使用双向链表实现队列&#xff0c;可以采用尾入&#xff0c;头出 也可以采用 头入、尾出 (LinkedList采用尾入、头出) 2. 下面代码实现的是尾入、头出&#xff1a; package bageight;/*** Created with IntelliJ IDEA.* Description:* User: tangyuxiu* Date: …

mOTA v2.0

mOTA v2.0 一、简介 本开源工程是一款专为 32 位 MCU 开发的 OTA 组件&#xff0c;组件包含了 bootloader 、固件打包器 (Firmware_Packager) 、固件发送器 三部分&#xff0c;并提供了基于多款 MCU (STM32F1 / STM32F407 / STM32F411 / STM32L4) 和 YModem-1K 协议的案例。基…

【文献及模型、制图分享】2000—2020年中国青饲料播种面积及供需驱动因素的时空格局

文献介绍 高产、优质的青饲料对于国家畜牧业发展和食物供给至关重要。然而&#xff0c;当前对于青饲料播种面积时空变化格局及其阶段性特征、区域差异以及影响因素等尚未清楚。 本文基于省级面板数据分析了2000—2020年青饲料种植的时空格局变化&#xff0c;结合MODIS-NPP产品…

Nginx 405 not allowed

问题原因&#xff1a;nginx不允许静态文件被post请求 解决&#xff1a;添加error_page 405 200 $request_uri;

白酒与家庭:团圆时刻的需备佳品

在中国传统文化中&#xff0c;家庭是社会的基石&#xff0c;是每个人心灵的港湾。而团圆&#xff0c;则是家庭生活中较美好的时刻。在这样一个特殊的日子里&#xff0c;白酒&#xff0c;尤其是豪迈白酒&#xff08;HOMANLISM&#xff09;&#xff0c;成为了团圆时刻的需备佳品。…

了解JS数组元素及属性

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1、定义数组并输出2、查询数组的长度3、访问数组的第一个元素4、访问数组中第一个元素的xxx属性5、从数组元素中提取ID并存储到搜索参数对象 提示&#xff1a;以下是…

C++设计模式1:单例模式(懒汉模式和饿汉模式,以及多线程问题处理)

饿汉单例模式 程序还没有主动获取实例对象&#xff0c;该对象就产生了&#xff0c;也就是程序刚开始运行&#xff0c;这个对象就已经初始化了。 class Singleton { public:~Singleton(){std::cout << "~Singleton()" << std::endl;}static Singleton* …

KUKA KR C2 中文操作指南 详情见目录

KUKA KR C2 中文操作指南 详情见目录

Selenium + Python 自动化测试22(PO+数据驱动)

我们的目标是&#xff1a;按照这一套资料学习下来&#xff0c;大家可以独立完成自动化测试的任务。 上一篇我们讨论了PO模式和unittest框架结合起来使用。 本篇文章我们综合一下之前学习的内容&#xff0c;如先将PO模式、数据驱动思想和我们生成HTML报告融合起来&#xff0c;综…

​2024年AI新蓝海:三门生意如何借AI之力,开启变现新篇章

【导语】在这个日新月异的时代&#xff0c;人工智能&#xff08;AI&#xff09;已不再是遥不可及的未来科技&#xff0c;而是正逐步渗透到我们生活的方方面面&#xff0c;成为推动产业升级的重要力量。你是否还在为传统行业的未来而忧虑&#xff1f;别担心&#xff0c;AI正以其…

Pandas DataFrame 数据转换处理和多条件查询

工作中需要处理一个比较大的数据&#xff0c;且当中需要分析的日期类型字段为字符串型&#xff0c;需要进行转换&#xff0c;获得一个新的字段用于时间统计。我们应用 datetime.datetime.strptime 函数进行转换。 数据读取与时间列补充代码如下&#xff1a; import pandas as…

原来ChatGPT是这么评价《黑神话:悟空》的啊?

《黑神话&#xff1a;悟空》一经上线便迅速吸引了全球的目光&#xff0c;成为了今日微博热搜榜上的焦点话题。作为中国首款现象级的中国3A大作&#xff0c;它的发布无疑引发了广泛的关注与讨论。 《黑神话&#xff1a;悟空》&#xff0c;这款3A国产游戏大作&#xff0c;由国内游…

根据状态的不同,显示不同的背景颜色

文章目录 前言HTML模板部分JavaScript部分注意&#xff1a;主要差异影响如何处理示例 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 实现效果&#xff1a; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 根据给定的状态…

文件操作2(函数的专栏)

1、文件的打开和关闭 1.1文件指针 在缓冲文件系统中&#xff0c;关键的概念是“文件类型指针”&#xff0c;简称“文件指针”取名为FILE。 例如&#xff0c; VS2013编译环境提供的 stdio. h头文件中有以下的文件类型申明&#xff1a; struct _ iobuf { char *_ ptr; int _…

【YOLO5 项目实战】(6)YOLO5+StrongSORT 目标追踪

欢迎关注『youcans动手学模型』系列 本专栏内容和资源同步到 GitHub/youcans 【YOLO5 项目实战】&#xff08;1&#xff09;YOLO5 环境配置与检测 【YOLO5 项目实战】&#xff08;2&#xff09;使用自己的数据集训练目标检测模型 【YOLO5 项目实战】&#xff08;6&#xff09;Y…

数据库机器上停service360safe

发现有个数据库的负载较高&#xff0c;发现有360safe&#xff0c;就准备停了该服务再观察 [rootdb1 ~]# ps -ef |grep 360 root 970 1 0 15:12 ? 00:00:10 /opt/360safe/360entclient root 976 970 5 15:12 ? 00:18:42 /opt/360…

Linux之RabbitMQ集群部署

RabbitMQ 消息中间件 1、消息中间件 消息(message)&#xff1a; 指在服务之间传送的数据。可以是简单的文本消息&#xff0c;也可以是包含复杂的嵌入对象的消息 消息队列(message queue): 指用来存放消息的队列&#xff0c;一般采用先进先出的队列方式&#xff0c;即最先进入的…