Java Queue接口及其常用实现类分析

简介: Java Queue接口及其常用实现类分析

Java集合框架中,Queue接口代表了一个队列,它是一种特殊的线性表,只允许在表的前端(front)进行删除操作,在表的后端(rear)进行插入操作。队列是一种先进先出(FIFO)的数据结构,即最先插入的元素将最先被删除。Java中的Queue接口提供了多种方法来操作队列中的元素,并且有多种实现类来满足不同的使用场景。


一、Queue接口的主要方法


  • add(E e): 将指定的元素插入此队列(如果立即可行且不会违反容量限制),成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException
  • offer(E e): 将指定的元素插入此队列(如果立即可行且不会违反容量限制),成功时返回 true,如果当前没有可用的空间,则返回 false
  • remove(): 检索并删除此队列的头,如果此队列为空,则抛出 NoSuchElementException
  • poll(): 检索并删除此队列的头,或返回 null 如果此队列为空。
  • element(): 检索但不删除此队列的头,如果此队列为空,则抛出 NoSuchElementException
  • peek(): 检索但不删除此队列的头,或返回 null 如果此队列为空。


二、常用实现类


  1. LinkedList
    LinkedList类实现了Queue接口,因此它可以作为队列使用。由于其内部使用双向链表实现,所以插入和删除操作都具有较高的效率。
  2. PriorityQueue
    PriorityQueue是一个基于优先级堆的无界队列。它的头部是按指定排序方式确定的最小元素。如果多个元素都是最小值,则任何一个都可能被找到。
  3. ArrayDeque
    ArrayDeque是一个双端队列,实现了Queue接口,也可以当作栈来使用。它通常比LinkedList提供更高的性能,是并发编程中首选的队列实现之一。
  4. ConcurrentLinkedQueue
    ConcurrentLinkedQueue是一个适用于多线程编程的线程安全队列,它使用高效的非阻塞算法来实现并发访问。
  5. SynchronousQueue
    SynchronousQueue是一个没有存储空间的阻塞队列,它每个插入操作必须等待一个相应的删除操作,反之亦然。


三、示例代码


下面是一些使用不同队列实现类的示例代码:

import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.ArrayDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.SynchronousQueue;
public class QueueExample {
    public static void main(String[] args) {
        // 使用LinkedList作为队列
        Queue<String> linkedListQueue = new LinkedList<>();
        linkedListQueue.offer("A");
        linkedListQueue.offer("B");
        System.out.println(linkedListQueue.poll()); // 输出 A
        // 使用PriorityQueue作为优先队列
        Queue<Integer> priorityQueue = new PriorityQueue<>();
        priorityQueue.offer(3);
        priorityQueue.offer(1); // 小的数字有更高的优先级
        System.out.println(priorityQueue.poll()); // 输出 1
        // 使用ArrayDeque作为双端队列(也可以作为栈使用)
        Queue<Integer> arrayDeque = new ArrayDeque<>();
        arrayDeque.offer(1);
        arrayDeque.offer(2); // 在尾部添加元素
        System.out.println(arrayDeque.poll()); // 输出 1
        // 使用ConcurrentLinkedQueue作为线程安全队列
        Queue<String> concurrentQueue = new ConcurrentLinkedQueue<>();
        concurrentQueue.offer("Thread-Safe"); // 在并发环境中安全地添加元素
        System.out.println(concurrentQueue.poll()); // 输出 Thread-Safe
        // 使用SynchronousQueue作为同步队列的示例(需要额外的线程来消费)
        // 这里只是演示如何创建它,实际上你会在两个线程中使用它来实现生产者-消费者模式。
        Queue<Integer> synchronousQueue = new SynchronousQueue<>();
        // synchronousQueue.offer(1); // 这会阻塞,因为没有消费者在等待接收数据。
    }
}

注意:在上面的代码中,SynchronousQueue的示例并没有实际执行offer()方法,因为这会立即阻塞当前线程,直到有另一个线程调用poll()或相应的删除方法来接收这个元素。在实际使用中,你会看到这种队列与生产者-消费者模式一起使用,其中生产者和消费者在不同的线程中运行。

Java Queue接口及其常用实现类分析

在Java集合框架中,Queue接口代表了一个队列,它是一种特殊的线性表,只允许在表的前端(front)进行删除操作,在表的后端(rear)进行插入操作。队列是一种先进先出(FIFO)的数据结构,即最先插入的元素将最先被删除。Java中的Queue接口提供了多种方法来操作队列中的元素,并且有多种实现类来满足不同的使用场景。

一、Queue接口的主要方法

  • add(E e): 将指定的元素插入此队列(如果立即可行且不会违反容量限制),成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException
  • offer(E e): 将指定的元素插入此队列(如果立即可行且不会违反容量限制),成功时返回 true,如果当前没有可用的空间,则返回 false
  • remove(): 检索并删除此队列的头,如果此队列为空,则抛出 NoSuchElementException
  • poll(): 检索并删除此队列的头,或返回 null 如果此队列为空。
  • element(): 检索但不删除此队列的头,如果此队列为空,则抛出 NoSuchElementException
  • peek(): 检索但不删除此队列的头,或返回 null 如果此队列为空。


二、常用实现类


  1. LinkedList
    LinkedList类实现了Queue接口,因此它可以作为队列使用。由于其内部使用双向链表实现,所以插入和删除操作都具有较高的效率。
  2. PriorityQueue
    PriorityQueue是一个基于优先级堆的无界队列。它的头部是按指定排序方式确定的最小元素。如果多个元素都是最小值,则任何一个都可能被找到。
  3. ArrayDeque
    ArrayDeque是一个双端队列,实现了Queue接口,也可以当作栈来使用。它通常比LinkedList提供更高的性能,是并发编程中首选的队列实现之一。
  4. ConcurrentLinkedQueue
    ConcurrentLinkedQueue是一个适用于多线程编程的线程安全队列,它使用高效的非阻塞算法来实现并发访问。
  5. SynchronousQueue
    SynchronousQueue是一个没有存储空间的阻塞队列,它每个插入操作必须等待一个相应的删除操作,反之亦然。


三、示例代码


下面是一些使用不同队列实现类的示例代码:

import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.ArrayDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.SynchronousQueue;
public class QueueExample {
    public static void main(String[] args) {
        // 使用LinkedList作为队列
        Queue<String> linkedListQueue = new LinkedList<>();
        linkedListQueue.offer("A");
        linkedListQueue.offer("B");
        System.out.println(linkedListQueue.poll()); // 输出 A
        // 使用PriorityQueue作为优先队列
        Queue<Integer> priorityQueue = new PriorityQueue<>();
        priorityQueue.offer(3);
        priorityQueue.offer(1); // 小的数字有更高的优先级
        System.out.println(priorityQueue.poll()); // 输出 1
        // 使用ArrayDeque作为双端队列(也可以作为栈使用)
        Queue<Integer> arrayDeque = new ArrayDeque<>();
        arrayDeque.offer(1);
        arrayDeque.offer(2); // 在尾部添加元素
        System.out.println(arrayDeque.poll()); // 输出 1
        // 使用ConcurrentLinkedQueue作为线程安全队列
        Queue<String> concurrentQueue = new ConcurrentLinkedQueue<>();
        concurrentQueue.offer("Thread-Safe"); // 在并发环境中安全地添加元素
        System.out.println(concurrentQueue.poll()); // 输出 Thread-Safe
        // 使用SynchronousQueue作为同步队列的示例(需要额外的线程来消费)
        // 这里只是演示如何创建它,实际上你会在两个线程中使用它来实现生产者-消费者模式。
        Queue<Integer> synchronousQueue = new SynchronousQueue<>();
        // synchronousQueue.offer(1); // 这会阻塞,因为没有消费者在等待接收数据。
    }
}

注意:在上面的代码中,SynchronousQueue的示例并没有实际执行offer()方法,因为这会立即阻塞当前线程,直到有另一个线程调用poll()或相应的删除方法来接收这个元素。在实际使用中,你会看到这种队列与生产者-消费者模式一起使用,其中生产者和消费者在不同的线程中运行。

相关文章
|
2月前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
160 57
|
11天前
|
JSON Java Apache
Java基础-常用API-Object类
继承是面向对象编程的重要特性,允许从已有类派生新类。Java采用单继承机制,默认所有类继承自Object类。Object类提供了多个常用方法,如`clone()`用于复制对象,`equals()`判断对象是否相等,`hashCode()`计算哈希码,`toString()`返回对象的字符串表示,`wait()`、`notify()`和`notifyAll()`用于线程同步,`finalize()`在对象被垃圾回收时调用。掌握这些方法有助于更好地理解和使用Java中的对象行为。
|
10天前
|
缓存 算法 搜索推荐
Java中的算法优化与复杂度分析
在Java开发中,理解和优化算法的时间复杂度和空间复杂度是提升程序性能的关键。通过合理选择数据结构、避免重复计算、应用分治法等策略,可以显著提高算法效率。在实际开发中,应该根据具体需求和场景,选择合适的优化方法,从而编写出高效、可靠的代码。
25 6
|
14天前
|
数据采集 JSON Java
利用Java获取京东SKU接口指南
本文介绍如何使用Java通过京东API获取商品SKU信息。首先,需注册京东开放平台账号并创建应用以获取AppKey和AppSecret。接着,查阅API文档了解调用方法。明确商品ID后,构建请求参数并通过HTTP客户端发送请求。最后,解析返回的JSON数据提取SKU信息。注意遵守API调用频率限制及数据保护法规。此方法适用于电商平台及其他数据获取场景。
|
19天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
46 6
|
2月前
|
监控 算法 Java
jvm-48-java 变更导致压测应用性能下降,如何分析定位原因?
【11月更文挑战第17天】当JVM相关变更导致压测应用性能下降时,可通过检查变更内容(如JVM参数、Java版本、代码变更)、收集性能监控数据(使用JVM监控工具、应用性能监控工具、系统资源监控)、分析垃圾回收情况(GC日志分析、内存泄漏检查)、分析线程和锁(线程状态分析、锁竞争分析)及分析代码执行路径(使用代码性能分析工具、代码审查)等步骤来定位和解决问题。
|
2月前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
65 8
|
2月前
|
Java API
Java中内置的函数式接口
Java中内置的函数式接口
27 2
|
2月前
|
Java
在Java中,接口之间可以继承吗?
接口继承是一种重要的机制,它允许一个接口从另一个或多个接口继承方法和常量。
126 1
|
9天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者