Java中的AbstractQueue和示例
Java中的 AbstractQueue 类是Java Collection Framework的一部分,实现了 _ Collection_ 接口和 AbstractCollection 类。它提供了一些 Queue 操作的骨架实现。该类中的实现适用于基础实现不允许空元素的情况。方法 add , remove 和 element 基于offer,poll和peek,但是它们会抛出异常而不是返回false或null表示失败。
类层次结构:
java.lang.Object
↳ java.util.AbstractCollection<E>
↳ Class AbstractQueue<E>
该类实现了Iterable <E>
, Collection <E>
和 Queue <E>
接口,并继承了AbstractCollection类。
声明:
public abstract class AbstractQueue<E> extends AbstractCollection<E> implements Queue<E>
E – 由Collection Framework类或接口维护的元素类型。
Java AbstractQueue中的构造函数
由于AbstractQueue是一个抽象类,它的实现是由其子类提供的。以下显示了可以提供实现的类列表。要创建它,我们需要从 java.util.AbstractQueue 创建它。
protected AbstractQueue() :默认构造函数,但由于它是抽象的,不允许创建AbstractQueue对象。其实现应由其子类之一提供,如ArrayBlockingQueue,ConcurrentLinkedQueue,DelayQueue,LinkedBlockingDeque,LinkedBlockingQueue,LinkedTransferQueue,PriorityBlockingQueue,PriorityQueue,SynchronousQueue。
AbstractQueue<E> objName = new ArrayBlockingQueue<E>();
以下是一个示例程序,用于说明Java中的AbstractQueue:
// Java code to illustrate AbstractQueue
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
public class AbstractQueueExample {
public static void main(String[] argv) throws Exception
{
// Creating object of AbstractQueue<Integer>
AbstractQueue<Integer> AQ = new LinkedBlockingQueue<Integer>();
// Adding elements to the Queue
AQ.add(10);
AQ.add(20);
AQ.add(30);
AQ.add(40);
AQ.add(50);
// print the queue contents to the console
System.out.println("AbstractQueue contains: " + AQ);
}
}
输出:
AbstractQueue contains: [10, 20, 30, 40, 50]
基本操作
1. 添加元素
要将元素添加到AbstractQueue中,它提供了两种方法。add(E e)方法如果可以立即将指定元素插入到此队列中而不违反容量限制,则将其插入到此队列中。如果当前没有空间,则返回true并抛出IllegalStateException。addAll(E e)方法将指定集合中的所有元素添加到此队列中。
// Java程序演示如何向AbstractQueue中添加元素
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
public class AddingElementsExample {
public static void main(String[] argv) throws Exception
{
// 因为AbstractQueue是一个抽象类,
// 所以使用LinkedBlockingQueue创建对象
AbstractQueue<Integer> AQ1 = new LinkedBlockingQueue<Integer>();
// 向AQ中添加元素
AQ1.add(10);
AQ1.add(20);
AQ1.add(30);
AQ1.add(40);
AQ1.add(50);
// 打印AQ中的元素
System.out.println("AbstractQueue contains : "
+ AQ1);
// 因为AbstractQueue是一个抽象类,
// 所以使用LinkedBlockingQueue创建对象
AbstractQueue<Integer> AQ2 = new LinkedBlockingQueue<Integer>();
// 初始状态下打印AQ2中的元素
System.out.println("AbstractQueue2 initially contains : " + AQ2);
// 将AQ1中的元素添加到AQ2中
AQ2.addAll(AQ1);
System.out.println( "AbstractQueue1 after addition contains : " + AQ2);
}
}
输出
AbstractQueue contains : [10, 20, 30, 40, 50]
AbstractQueue2 initially contains : []
AbstractQueue1 after addition contains : [10, 20, 30, 40, 50]
2. 移除元素
要从AbstractQueue中移除元素,它提供了 remove() 和 clear() 方法。
- remove() 方法返回并移除此队列的头。
- clear() 方法从此队列中移除所有元素。调用该方法后,队列将为空。
// Java程序演示如何从AbstractQueue中移除元素
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
public class RemovingElementsExample {
public static void main(String[] argv) throws Exception
{
// 因为AbstractQueue是一个抽象类,
// 所以使用LinkedBlockingQueue创建对象
AbstractQueue<Integer> AQ1 = new LinkedBlockingQueue<Integer>();
// 使用 add() 方法添加元素
AQ1.add(10);
AQ1.add(20);
AQ1.add(30);
AQ1.add(40);
AQ1.add(50);
// 向控制台打印队列内容
System.out.println("AbstractQueue1 contains : " + AQ1);
// 检索队列头部
int head = AQ1.remove();
// 打印头部元素
System.out.println("head : " + head);
// 打印修改后的队列
System.out.println("AbstractQueue1 after removal of head : " + AQ1);
// 移除所有元素
AQ1.clear();
// 打印修改后的队列
System.out.println("AbstractQueue1 : " + AQ1);
}
}
输出
AbstractQueue1 contains : [10, 20, 30, 40, 50]
head : 10
AbstractQueue1 after removal of head : [20, 30, 40, 50]
AbstractQueue1 : []
3. 访问元素
AbstractQueue的element()方法检索但不删除此队列的头。
// Java程序,演示从AbstractQueue中访问元素
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
public class AccessingElementExample {
public static void main(String[] argv) throws Exception
{
// 由于AbstractQueue是一个抽象类,
// 因此使用LinkedBlockingQueue创建对象
AbstractQueue<Integer> AQ1 = new LinkedBlockingQueue<Integer>();
// 使用add方法填充AQ1
AQ1.add(10);
AQ1.add(20);
AQ1.add(30);
AQ1.add(40);
AQ1.add(50);
// 将AQ输出到控制台
System.out.println("AbstractQueue1包含: " + AQ1);
// 访问头元素
System.out.println("head: " + AQ1.element());
}
}
输出
AbstractQueue1包含: [10,20,30,40,50]
head: 10
AbstractQueue的方法
方法 | 描述 |
---|---|
add(E e) | 如果可以立即无违反容量限制地将指定元素插入此队列,则返回true;如果当前没有可用空间,则抛出IllegalStateException。 |
addAll(Collection c) | 将指定集合中的所有元素添加到此队列中。 clear() | 从此队列中移除所有元素。 element() | 检索但不移除此队列的头部。 remove() | 检索并删除此队列的头。 ### AbstractCollection类声明的方法 方法 | 描述 |
如果此集合包含指定集合中的所有元素,则返回true。 |
为空() | 如果此集合不包含元素,则返回true。 |
迭代器() | 返回迭代器,用于遍历此集合中包含的元素。 |
remove(Object o) | 如果存在(可选操作),则从此集合中删除指定元素的单个实例。 |
removeAll(Collection> c) | 删除也包含在指定集合中的此集合的所有元素(如果存在)(可选操作)。 retainAll(Collection> c) |
仅保留此集合中包含在指定集合中的元素(如果存在)(可选操作)。 |
toArray() | 返回包含此集合中所有元素的数组。 |
java.util.Collection接口声明的方法
方法 | 描述 | |
---|---|---|
contains(Object o) | 如果此集合包含指定的元素,则返回true。 | |
containsAll(Collection> c) | 如果此集合包含指定集合中的所有元素,则返回true。 equals(Object o) | 将指定的对象与此集合进行比较,以实现相等性。 hashCode() | 返回此集合的哈希码值。 isEmpty() | 如果此集合不包含元素,则返回true。 iterator() | 返回此集合中的元素上的迭代器。 parallelStream() | 返回一个可能是并行流的,其源为此集合的流。 remove(Object o) | 如果存在(可选操作),则从此集合中删除指定元素的单个实例。 removeAll(Collection> c) |
删除此集合中也包含在指定集合中的所有元素(可选操作)。 | |
removeIf(Predicate super E> filter) | 删除满足给定谓词的此集合的所有元素。 retainAll(Collection> c) |
仅保留在此集合中包含在指定集合中的元素(可选操作)。 | |
size() | 返回此集合中的元素数。 | |
spliterator() | 在此集合中的元素上创建Spliterator。 | |
stream() | 返回一个其源为此集合的顺序流。 | |
toArray() | 返回包含此集合中所有元素的数组。 | |
toArray(IntFunction<T[]> generator) | 使用提供的生成器函数分配返回的数组,返回包含此集合中所有元素的数组。 | |
toArray(T[] a) | 返回包含此集合中所有元素的数组;返回的数组的运行时类型为指定数组的类型。 |
Iterable接口声明的方法
方法 | 描述 |
---|---|
forEach(Consumer<? super T> action) | 对可迭代对象的每个元素执行给定的操作,直到处理完所有元素或操作引发异常。 |
Queue接口声明的方法
方法 | 描述 |
---|---|
offer(E e) | 如果可以立即这样做而不违反容量限制,则将指定元素插入此队列。 |
peek() | 检索但不删除此队列的头部,如果此队列为空,则返回null。 |
poll() | 检索并删除此队列的头部,如果此队列为空,则返回null。 |
参考: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/AbstractQueue.html
解释
在Java中,抽象队列是一种遵循FIFO(先进先出)原则的数据结构,这意味着添加到队列中的第一个元素是第一个被删除的元素。抽象队列是一个抽象类,作为Java中各种队列实现的基类。
抽象队列提供一组公共方法,这些方法对所有队列实现都是通用的,例如向队列的末尾添加元素,从队列的前端删除元素,以及查看位于队列前端的元素而不删除它。这些方法在抽象类中定义,可以被具体的队列实现覆盖重写。
抽象队列类提供的一些常用方法包括:
add():该方法用于将元素添加到队列的末尾。如果队列已满,则抛出异常。
offer():该方法用于将元素添加到队列的末尾。如果队列已满,则返回false。
remove():该方法用于删除并返回位于队列前端的元素。如果队列为空,则抛出异常。
poll():该方法用于删除并返回位于队列前端的元素。如果队列为空,则返回null。
element():该方法用于获取并查看位于队列前端的元素,而不将其从队列中删除。如果队列为空,则抛出异常。
peek():该方法用于获取并查看位于队列前端的元素,而不将其从队列中删除。如果队列为空,则返回null。
Java中抽象队列的一些具体实现包括:
LinkedList:Java中的LinkedList类实现了Queue接口,并提供了抽象队列的具体实现。
ArrayDeque:Java中的ArrayDeque类提供了动态数组实现抽象队列的具体方法。
PriorityQueue:Java中的PriorityQueue类提供了一个基于优先堆的无限制优先级队列。
在需要按添加顺序处理元素的各种应用程序中,Java中的抽象队列是一种有用的工具。它用于以下情况:
在消息系统中实现消息队列。
在多线程应用程序中实现任务队列。
在流系统中实现数据处理缓冲区。
总的来说,Java中的抽象队列是以先进先出方式管理数据集合的多功能强大工具。
程序
import java.util.Queue;
import java.util.LinkedList;
public class QueueExample {
public static void main(String[] args) {
// 创建一个新队列
Queue<String> queue = new LinkedList<>();
// 将元素添加到队列中
queue.add("Alice");
queue.add("Bob");
queue.add("Charlie");
queue.add("David");
// 打印队列中的元素
System.out.println("Queue: " + queue);
// 从队列中删除第一个元素
String first = queue.remove();
System.out.println("Removed element: " + first);
// 打印队列中剩余的元素
System.out.println("Queue: " + queue);
// 查看队列的第一个元素
String peeked = queue.peek();
System.out.println("Peeked element: " + peeked);
// 打印队列中剩余的元素
System.out.println("Queue: " + queue);
}
}
输出
Queue: [Alice, Bob, Charlie, David]
Removed element: Alice
Queue: [Bob, Charlie, David]
Peeked element: Bob
Queue: [Bob, Charlie, David]
在这个例子中,我们使用具体的实现LinkedList创建一个新的队列。然后我们向队列中添加四个元素,并使用System.out.println()语句打印这些元素。
然后我们使用remove()方法从队列中删除第一个元素,并打印已删除的元素。然后我们再次使用System.out.println()语句打印队列中剩余的元素。
然后我们使用peek()方法查看队列中的第一个元素,并打印该元素。最后,我们再次使用System.out.println()语句打印队列中剩余的元素。
时间和空间复杂度
Java中抽象队列的时间和空间复杂度取决于使用的具体实现。在这个例子中,我们使用LinkedList来实现队列。
LinkedList的各种操作的时间复杂度如下:
add(element):O(1)
remove():O(1)
peek():O(1)
因此,将元素添加到队列中,从队列中删除元素以及查看队列中第一个元素的时间复杂度都是O(1)。
使用LinkedList实现的队列的空间复杂度是O(n),其中n是队列中的元素数量。这是因为LinkedList在内部使用动态数组来存储其元素,随着添加或删除元素,该数组可能需要调整大小。然而,确切的空间复杂度可能取决于LinkedList类的实现细节。
总之,在使用LinkedList实现的抽象队列中添加,删除和查看元素的时间复杂度为O(1),而空间复杂度为O(n)