Java队列
Java Queue接口java.util.Queue表示一种数据结构,设计为在队列末尾插入元素,并从队列开头删除元素。这类似于超市中的队列工作方式。
JavaQueue
接口是Java Collection接口的子类型。它表示对象的有序序列,就像Java列表一样,但是其预期用途略有不同。因为Java Queue接口是JavaCollection
接口的子类型,所以Queue
接口中也提供了Collection
接口中的所有方法。
Java队列实现
由于Queue是一个接口,因此我们需要实例化该接口的具体实现才能使用它。我们可以在Java Collections API的以下" Queue"实现之间进行选择:
- java.util.LinkedList
- java.util.PriorityQueue
LinkedList是一个非常标准的队列实现。队列中的元素内部存储在标准链表数据结构中。这样可以快速将元素插入列表的末尾(尾部),并从列表的开头(头)除去元素。
" PriorityQueue"根据其自然顺序(如果它们实现" Comparable")或者根据传递给" PriorityQueue"的" Comparator"在内部存储其元素。
以下是一些如何创建Queue
实例的示例:
Queue queueA = new LinkedList(); Queue queueB = new PriorityQueue();
在大多数"队列"实现中,队列的头和尾在相反的两端。但是,可以实现" Queue"接口,以使队列的头尾在同一端。在这种情况下,我们将拥有一个堆栈。
通用队列
默认情况下,我们可以将任何"对象"放入"队列",但是从Java 5开始,Java泛型可以限制我们可以插入"队列"的对象的类型。这是一个例子:
Queue<MyObject> queue = new LinkedList<MyObject>();
现在,该"队列"只能插入" MyObject"实例。然后,我们可以访问和迭代其元素,而无需强制转换它们。外观如下:
Queue<MyObject> queue = new LinkedList<MyObject>(); MyObject myObject = queue.remove(); for(MyObject anObject : queue){ //do someting to anObject... }
注意,第一行不需要强制转换,并且for-each循环如何将Queue的每个元素直接强制转换为MyObject实例。这是可能的,因为队列是使用MyObject作为通用类型创建的。
如果知道的话,总是为Queue指定通用类型是一种好习惯。这有助于Java编译器检查类型,编写更紧凑的代码,并帮助代码的下一个阅读者了解此Queue包含哪些对象类型。有关Java泛型的更多信息,请参见Java泛型教程。
将元素添加到队列
Java Queue接口包含两种方法,可用于将元素添加到Queue中。这些方法是add()
方法和offer()
方法。这两种方法将元素添加到队列的末尾。 add()和offer()方法在队列已满的情况下的行为方式有所不同,因此无法添加更多元素。在这种情况下,add()
方法会引发异常,而offer()
方法只会返回" false"。这是两个通过其add()
和offer()
方法向Java Queue添加元素的示例:
Queue<String> queue = new LinkedList<>(); queue.add("element 1"); queue.offer("element 2");
从队列中取出元素
要从Java队列中获取元素,可以调用其poll()
或者remove()
方法。 poll()
和remove()都删除队列中的第一个元素。如果队列为空,它们的行为方式有所不同。如果Queue为空,则poll()
方法返回null
。如果Queue为空,则remove()
方法将引发异常。以下是两个使用Java队列中的poll()
和remove()
方法获取元素的示例:
Queue<String> queue = new LinkedList<>(); queue.add("element 1"); queue.add("element 2"); String element1 = queue.poll(); String element2 = queue.remove();
对poll()
的调用将删除Queue的第一个元素,这是第一个添加了" element 1"的Java String实例。
对rmove()
的调用将删除Queue的第二个元素,该元素在第一个poll()调用之后现在是String实例添加的" element 2"。
窥视队列
我们可以窥视"队列"顶部的元素,而无需将该元素从"队列"中取出。这是通过Queue的element()或者peek()方法完成的。
element()方法返回Queue中的第一个元素。如果Queue为空,则element()方法抛出NoSuchElementException。这是一个使用element()方法窥视Java Queue的第一个元素的示例:
Queue<String> queue = new LinkedList<>(); queue.add("element 1"); queue.add("element 2"); queue.add("element 3"); String firstElement = queue.element();
运行此Java代码后," firstElement"变量将包含值" element 1",这是" Queue"中的第一个元素。
peek()与element()方法类似,但是如果Queue为空则不会抛出异常。相反,它只返回" null"。这是一个使用peek()
方法来查看'Queue'的第一个元素的示例:
Queue<String> queue = new LinkedList<>(); queue.add("element 1"); queue.add("element 2"); queue.add("element 3"); String firstElement = queue.peek();
从队列中删除元素
要从JavaQueue
中删除元素,可以调用remove()
方法。此方法删除"队列"开头的元素。
这是从Java队列中删除元素的示例:
Queue<String> queue = new LinkedList<>(); queue.add("element 0"); queue.add("element 1"); String removedElement = queue.remove();
从队列中删除所有元素
我们可以使用它的clear()
方法从Java队列中删除所有元素。 clear()方法实际上是从Collection接口继承的。这是一个通过其clear()方法从Java队列中删除所有元素的示例:
queue.clear();
获取队列大小
我们可以通过Java Queue的size()方法读取存储其中的元素数量。这是一个通过它的size()方法获取Java队列大小的示例:
Queue<String> queue = new LinkedList<>(); queue.add("element 1"); queue.add("element 2"); queue.add("element 3"); int size = queue.size();
运行此代码后,size
变量应包含值3,因为在调用size()
时队列包含3个元素。
检查队列是否包含元素
我们可以通过其" contains()"方法检查Java队列是否包含某个元素。如果Queue包含给定的元素,则contains()方法将返回true,否则返回false。实际上,contains()方法是从Collection接口继承的,但实际上并不重要。这是检查Java队列是否包含给定元素的两个示例:
Queue<String> queue = new LinkedList<>(); queue.add("Mazda"); boolean containsMazda = queue.contains("Mazda"); boolean containsHonda = queue.contains("Honda");
运行此代码后,containsMazda
变量将具有值'true',而containsHonda
变量将具有值'false',因为队列包含" Mazda"字符串元素,但不包含" Honda"字符串元素。
迭代队列中的所有元素
我们还可以迭代Java队列的所有元素,而不必一次处理一个。这是一个迭代Java队列中所有元素的示例:
Queue<String> queue = new LinkedList<>(); queue.add("element 0"); queue.add("element 1"); queue.add("element 2"); //access via Iterator Iterator<String> iterator = queue.iterator(); while(iterator.hasNext(){ String element = iterator.next(); } //access via new for-loop for(String element : queue) { //do something with each element }
当通过其"迭代器"或者通过for-each循环(也使用幕后的迭代器)迭代"队列"时,元素迭代的顺序取决于队列的实现。