Java Queue接口
队列简介
在Java集合框架中,Queue(队列)是一种特殊的线性集合,它遵循先进先出(FIFO - First-In-First-Out)的原则,即最先添加的元素最先被移除。Queue接口位于java.util
包中,是Collection接口的子接口,主要用于在处理元素前保存元素。
队列的形象比喻就是现实生活中的排队场景:排在队伍最前面的人最先得到服务,新来的人只能排在队尾。
Queue接口的核心方法
Queue接口定义了以下几个核心方法,每个方法的行为在出错/失败情况下有两种不同的表现形式:
操作类型 | 抛出异常的方法 | 返回特殊值的方法 |
---|---|---|
插入 | add(e) | offer(e) |
移除 | remove() | poll() |
检查 | element() | peek() |
方法详解
-
插入操作:
boolean add(E e)
: 将元素添加到队列,如果队列已满则抛出IllegalStateException
boolean offer(E e)
: 将元素添加到队列,如果成功返回true,队列已满则返回false
-
移除操作:
E remove()
: 移除并返回队头元素,如果队列为空则抛出NoSuchElementException
E poll()
: 移除并返回队头元素,如果队列为空则返回null
-
检查操作:
E element()
: 返回队头元素但不移除,如果队列为空则抛出NoSuchElementException
E peek()
: 返回队头元素但不移除,如果队列为空则返回null
在选择方法时,建议根据你对错误情况的处理需求来决定使用哪一组方法:
- 如果你希望在操作失败时抛出异常,使用 add/remove/element
- 如果你希望通过返回值判断操作是否成功,使用 offer/poll/peek
Queue的主要实现类
LinkedList
LinkedList
既实现了List
接口,也实现了Queue
接口。作为队列使用时,它提供了FIFO的队列操作。
import java.util.LinkedList;
import java.util.Queue;
public class LinkedListQueueExample {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
// 添加元素
queue.offer("Java");
queue.offer("Python");
queue.offer("C++");
System.out.println("队列: " + queue);
// 访问队列头部元素
System.out.println("队头元素: " + queue.peek());
// 移除元素
String removed = queue.poll();
System.out.println("移除的元素: " + removed);
System.out.println("移除后的队列: " + queue);
}
}
输出:
队列: [Java, Python, C++]
队头元素: Java
移除的元素: Java
移除后的队列: [Python, C++]
PriorityQueue
PriorityQueue
是一个基于优先级堆的队列,元素按照自然顺 序或者比较器(Comparator)指定的顺序排序。队列头部的元素总是优先级最高(最小)的元素。
import java.util.PriorityQueue;
import java.util.Queue;
public class PriorityQueueExample {
public static void main(String[] args) {
// 创建一个优先队列
Queue<Integer> priorityQueue = new PriorityQueue<>();
// 添加元素
priorityQueue.offer(5);
priorityQueue.offer(1);
priorityQueue.offer(3);
priorityQueue.offer(2);
priorityQueue.offer(4);
System.out.println("优先队列: " + priorityQueue);
// 移除元素(按优先级排序)
while (!priorityQueue.isEmpty()) {
System.out.println("移除: " + priorityQueue.poll());
}
}
}
输出:
优先队列: [1, 2, 3, 5, 4]
移除: 1
移除: 2
移除: 3
移除: 4
移除: 5
注意在上面的例子中,打印整个优先队列时显示的顺序可能看起来不是有序的,这是因为内部堆结构的表示。但是当我们使用poll()
方法逐个移除元素时,它们会按照优先级顺序(从小到大)被移除。
ArrayDeque
ArrayDeque
是一个基于数组实现的双端队列,它实现了Deque
接口,可以作为队列或栈来使用。作为队列使用时,它通常比LinkedList
有更好的性能。
import java.util.ArrayDeque;
import java.util.Queue;
public class ArrayDequeExample {
public static void main(String[] args) {
Queue<String> queue = new ArrayDeque<>();
// 添加元素
queue.offer("红");
queue.offer("橙");
queue.offer("黄");
System.out.println("队列: " + queue);
// 移除元素
String removed = queue.poll();
System.out.println("移除的元素: " + removed);
System.out.println("移除后的队列: " + queue);
}
}
输出:
队列: [红, 橙, 黄]
移除的元素: 红
移除后的队列: [橙, 黄]
阻塞队列
Java还提供了BlockingQueue
接口,它扩展了Queue
接口,主要用于生产者-消费者模式,提供了阻塞的插入和获取操作。当队列满时,插入操作将阻塞;当队列空时,获取操作将阻塞。
主要的实现类有:ArrayBlockingQueue
、LinkedBlockingQueue
、PriorityBlockingQueue
等。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class BlockingQueueExample {
public static void main(String[] args) throws InterruptedException {
// 创建容量为2的阻塞队列
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(2);
// 添加元素
blockingQueue.put("元素1");
blockingQueue.put("元素2");
System.out.println("队列已满: " + blockingQueue);
// 启动一个线程消费元素
new Thread(() -> {
try {
Thread.sleep(2000); // 等待2秒
System.out.println("消费者消费: " + blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 这里会阻塞,直到队列有空间
System.out.println("生产者等待放入元素...");
blockingQueue.put("元素3"); // 阻塞直到有空间
System.out.println("