Java教程适用于JDK 8。本页面中描述的示例和实践不利用后续版本引入的改进,并且可能使用不再可用的技术。
有关Java SE 9和后续版本中更新的语言特性的摘要,请参阅Java语言更改。
有关所有JDK版本的新功能、增强功能以及已删除或已弃用选项的信息,请参阅JDK版本说明。
一个Queue是在处理之前保存元素的集合。除了基本的Collection操作外,队列还提供了额外的插入、删除和检查操作。以下是Queue接口的定义。
public interface Queue<E> extends Collection<E> {
E element();
boolean offer(E e);
E peek();
E poll();
E remove();
}
每个Queue方法都有两种形式:(1)如果操作失败,抛出异常;(2)如果操作失败,则返回一个特殊值(根据操作的不同,可以是null或false)。接口的常规结构如下表所示。
| 操作类型 | 抛出异常 | 返回特殊值 |
|---|---|---|
| 插入 | add(e) |
offer(e) |
| 删除 | remove() |
poll() |
| 查看 | element() |
peek() |
队列通常(但不一定)以先进先出(FIFO)的方式对元素进行排序。优先级队列是一种例外,它根据元素的值进行排序 - 详见对象排序部分)。无论使用什么排序方式,队列的头部元素是通过调用remove或poll方法来删除的。在FIFO队列中,所有新元素都插入到队列的尾部。其他类型的队列可能使用不同的插入规则。每个Queue实现都必须指定其排序属性。
Queue实现可以限制它所保存的元素数量;这种队列称为有界队列。一些java.util.concurrent中的Queue实现是有界的,但java.util中的实现不是。
add方法是Queue从Collection继承的,它插入一个元素,除非它违反了队列的容量限制,否则会抛出IllegalStateException异常。offer方法只用于有界队列,与add方法的区别在于它通过返回false来表示插入元素失败。
remove和poll方法都会移除并返回队列的头部元素。具体移除的是哪个元素是由队列的排序策略决定的。当队列为空时,remove方法会抛出NoSuchElementException异常,而poll方法会返回null。
element和peek方法返回队列的头部元素,但不会将其移除。它们与remove和poll的区别与之相同:如果队列为空,element方法会抛出NoSuchElementException异常,而peek方法会返回null。
Queue实现通常不允许插入null元素。但是,LinkedList实现是一个例外,它被改造成实现Queue接口,并允许插入null元素,但你应该避免利用这一点,因为poll和peek方法会将null作为特殊返回值。
Queue实现通常不定义基于元素的equals和hashCode方法,而是继承自Object的基于身份的版本。
Queue接口没有定义阻塞队列方法,这在并发编程中很常见。这些方法等待元素出现或可用空间,它们被定义在接口java.util.concurrent.BlockingQueue中,该接口扩展了Queue接口。
在下面的示例程序中,使用队列实现了一个倒计时器。队列会预先加载从命令行指定的数字到零的所有整数值,按照降序排列。然后,这些值会在一秒的时间间隔内从队列中移除并打印出来。这个程序是人为的,因为在没有使用队列的情况下做同样的事情更自然,但它展示了在后续处理之前使用队列存储元素的用法。
import java.util.*;
public class Countdown {
public static void main(String[] args) throws InterruptedException {
int time = Integer.parseInt(args[0]);
Queue<Integer> queue = new LinkedList<Integer>();
for (int i = time; i >= 0; i--)
queue.add(i);
while (!queue.isEmpty()) {
System.out.println(queue.remove());
Thread.sleep(1000);
}
}
}
在下面的示例中,使用优先队列对一组元素进行排序。同样,这个程序是人为的,在使用Collections中提供的sort方法更好的情况下,没有理由使用它,但它展示了优先队列的行为。
static <E> List<E> 堆排序(Collection<E> c) {
Queue<E> 队列 = new PriorityQueue<E>(c);
List<E> 结果 = new ArrayList<E>();
while (!队列.isEmpty())
结果.add(队列.remove());
return 结果;
}