Java中的ArrayDeque
Java中的ArrayDeque提供了一种应用可调整大小的数组的方法,以及Deque接口的实现。它也被称为 _ Array Double Ended Queue_ 或 _ Array Deck_ 。这是一种特殊类型的数组,可以增长并允许用户从队列的两端添加或删除元素。
Java中的ArrayDeque类是使用可调整大小的数组存储其元素的Deque接口的实现。该类提供了传统Stack类的更有效的替代方法,该类以前用于双端操作。ArrayDeque类提供了从队列的两端插入和删除元素的常数时间性能,适用于需要执行许多添加和删除操作的情况。
这里是您如何在Java中使用ArrayDeque的示例:
import java.util.ArrayDeque;
import java.util.Deque;
public class Example {
public static void main(String[] args) {
Deque<Integer> deque = new ArrayDeque<>();
deque.addFirst(1);
deque.addLast(2);
int first = deque.removeFirst();
int last = deque.removeLast();
System.out.println("First: " + first + ", Last: " + last);
}
}
输出
First: 1, Last: 2
使用ArrayDeque的优点:
- 高效:ArrayDeque类提供了从队列的两端插入和删除元素的常数时间性能,适用于需要执行许多添加和删除操作的情况。
- 可调整大小:ArrayDeque类使用可调整大小的数组存储其元素,这意味着它可以动态增长和缩小以适应队列中的元素数量。
- 轻量级:ArrayDeque类是轻量级数据结构,不需要额外的开销(如链表节点),适用于内存有限的情况。
- 线程安全:ArrayDeque类不是线程安全的,但可以使用Collections.synchronizedDeque方法创建线程安全的ArrayDeque类的版本。
使用ArrayDeque的缺点:
- 未同步:默认情况下,ArrayDeque类不同步,这意味着多个线程可以同时访问它,导致潜在的数据损坏。
- 容量有限:尽管ArrayDeque类使用可调整大小的数组存储其元素,但它仍具有有限的容量,这意味着当旧的ArrayDeque达到其最大大小时,您可能需要创建一个新的ArrayDeque。
ArrayDeque的一些重要特征如下:
- ArrayDeque没有容量限制,根据需要增长以支持使用。
- 它们不是线程安全的,这意味着在缺乏外部同步的情况下,ArrayDeque不支持多个线程的并发访问。
- 空元素在ArrayDeque中被禁止。
- 当作为堆栈使用时,ArrayDeque类可能比Stack类更快。
- 当作为队列使用时,ArrayDeque类可能比LinkedList类更快。
ArrayDeque实现的接口:
ArrayDeque类实现了这两个接口:
- Queue 接口: 它是一个先进先出的数据结构接口,元素从后面添加进去。
- Deque 接口: 它是一个支持从两边插入元素的双端队列接口,是实现 Queue 接口的接口。
ArrayDeque 实现了 Queue 和 Deque 接口,它可以从两端动态调整大小,实现的所有接口继承关系是 序列化 , 克隆 , Iterable <E> , Collection <E> , Deque<E> , Queue<E>

语法: 声明
public class ArrayDeque<E>
继承 AbstractCollection<E>
实现 Deque<E>, Cloneable, Serializable
这里, E 是指元素类型,可以引用任何类,比如 Integer 或 String 等类。
现在我们知道了它的语法,下面让我们了解一下在实现之前定义的构造函数,以更好地理解并理解输出。
- ArrayDeque(): 这个构造函数用于创建一个空的 ArrayDeque,它默认具有容量来容纳 16 个元素。
ArrayDeque<E> dq = new ArrayDeque<E>();
- **ArrayDeque(Collection extends E> c): ** 这个构造函数用于创建一个与指定集合中的所有元素相同的 ArrayDeque。
“`java
ArrayDeque<E> dq = new ArrayDeque<E>(Collection col);
“`* **ArrayDeque(int numofElements):** 这个构造函数用于创建一个空的 ArrayDeque,它具有包含指定数量元素的容量。
“`java
ArrayDeque<E> dq = new ArrayDeque<E>(int numofElements);
“`ArrayDeque 中的方法如下:
**注意:** 这里, **元素** 是指 ArrayDeque 存储的元素类型。
方法 | 描述
—|—
add(Element e) | 该方法在队列末尾插入特定元素。
addAll(Collection extends E> c) | 将指定集合中的所有元素作为通过调用addLast(E)来的方式按其返回的集合迭代器的顺序添加到此队列的末尾。
addFirst(Element e) | 该方法在队列开头插入特定元素。
addLast(Element e) | 该方法在队列末尾插入特定元素。类似于add()方法。
clear() | 该方法删除所有队列元素。
clone() | 该方法复制队列。
contains(Obj) | 该方法检查队列是否包含元素。
element() | 该方法返回队列头部的元素。
forEach(Consumer super E> action) | 对Iterable的每个元素执行给定的操作,直到所有元素都已处理或操作抛出异常为止。
getFirst() | 该方法返回队列的第一个元素。
getLast() | 该方法返回队列的最后一个元素。
isEmpty() | 该方法检查队列是否为空。
iterator() | 返回此队列中元素的迭代器。
offer(Element e) | 该方法在队列末尾插入元素。
offerFirst(Element e) | 该方法在队列开头插入元素。
offerLast(Element e) | 该方法在队列末尾插入元素。
peek() | 该方法返回头部元素,但不删除它。
poll() | 该方法返回头部元素并将其删除。
pop() | 该方法用于由队列表示的栈弹出一个元素。
push(Element e) | 该方法用于将元素推入由队列表示的栈中。
remove() | 该方法返回头部元素并将其删除。
remove(Object o) | 从此deque中删除指定元素的单个实例。
removeAll(Collection> c) | 删除此集合中也包含在指定集合中的所有元素(可选操作)。
removeFirst() | 该方法返回第一个元素并将其删除。
removeFirstOccurrence(Object o) | 删除该deque中第一个出现的指定元素(从头到尾遍历deque)。
removeIf(Predicate super Element> filter) | 删除满足给定谓词的该集合的所有元素。
removeLast() | 该方法返回最后一个元素并将其删除。
removeLastOccurrence(Object o) | 删除该deque中最后一个出现的指定元素(从尾到头遍历deque)。
removeLastOccurrence(Object o) | 从deque中从头到尾遍历,删除指定元素的最后一个出现位置(可选操作)。
retainAll(Collection> c) | 仅保留包含在指定集合中的此集合中的元素(可选操作)。
size() | 返回此deque中元素的数量。
spliterator() | 在此deque中的元素上创建迟绑定和快速失败的Spliterator。
toArray() | 以正确的顺序(从第一个元素到最后一个元素)返回包含此deque中所有元素的数组。
toArray(T[] a) | 返回包含此deque中所有元素的数组,按正确的顺序(从第一个元素到最后一个元素);返回的数组的运行时类型是指定数组的类型。
继承自java.util.AbstractCollection类的方法
| 方法 | 执行的操作 |
|---|---|
| containsAll(Collection c) | 如果此集合包含指定集合中的所有元素,则返回true。 |
| toString() | 返回此集合的字符串表示形式。 |
继承自java.util.Collection接口的方法
| 方法 | 执行的操作 |
|---|---|
| containsAll(Collection c) | 如果此集合包含指定集合中的所有元素,则返回true。 |
| equals() | 将指定对象与此集合进行比较以实现相等性。 |
| hashcode() | 返回此集合的哈希码值。 |
| parallelStream() | 返回一个可能并行的Stream,其源为此集合。 |
| stream() | 返回一个顺序Stream,其源为此集合。 |
| toArray(IntFunction<T[]> generator) | 返回一个包含此集合中所有元素的数组,使用提供的生成函数来分配返回的数组。 |
在java.util.Deque接口中声明的方法
| 方法 | 执行的操作 |
|---|---|
| descendingIterator() | 返回一个迭代器,以与该deque的逆序顺序遍历该deque中的元素。 |
| peekFirst() | 检索但不删除此deque的第一个元素,如果此deque为空,则返回null。 |
| peekLast() | 检索但不删除此deque的最后一个元素,如果此deque为空,则返回null。 |
| pollFirst() | 检索并删除此deque的第一个元素,如果此deque为空,则返回null。 |
| pollLast() | 检索并删除此deque的最后一个元素,如果此deque为空,则返回null。 |
例子
// Java程序实现在Java中的ArrayDeque
//
//导入实用程序类
import java.util.*;
// ArrayDequeDemo
public class GGFG {
public static void main(String[] args)
{
// 创建并初始化deque
// 声明整数类型的对象
Deque<Integer> de_que = new ArrayDeque<Integer>(10);
// 操作1
// add() 方法
// 使用add()方法添加自定义元素插入
de_que.add(10);
de_que.add(20);
de_que.add(30);
de_que.add(40);
de_que.add(50);
// 使用forEach循环迭代
for (Integer element : de_que) {
// 打印相应的元素
System.out.println("元素 : " + element);
}
// 操作2
// clear() 方法
System.out.println("使用clear()");
// 使用clear()方法清除所有元素
de_que.clear();
// 操作3
// addFirst() 方法
// 在开头插入
de_que.addFirst(564);
de_que.addFirst(291);
// 操作4
// addLast() 方法
// 在末尾插入
de_que.addLast(24);
de_que.addLast(14);
// 显示消息
System.out.println("上述元素现在被删除");
// 迭代器
// 显示消息
System.out.println("使用迭代器的deque元素:");
for (Iterator itr = de_que.iterator();
itr.hasNext();) {
System.out.println(itr.next());
}
// descendingIterator()
// 反转deque的顺序
System.out.println("deque的元素反转顺序:");
for (Iterator dItr = de_que.descendingIterator();
dItr.hasNext();) {
System.out.println(dItr.next());
}
// 操作5
// element() 方法: 获取头元素
System.out.println("\n使用element()获取头元素: "
+ de_que.element());
// 操作6
// getFirst() 方法: 获取头元素
System.out.println("使用getFirst()获取头元素: "
+ de_que.getFirst());
// 操作7
// getLast() 方法: 获取最后一个元素
System.out.println("使用getLast()获取最后一个元素: "
+ de_que.getLast());
// 操作8
// toArray() 方法:
Object[] arr = de_que.toArray();
System.out.println("\n数组大小: " + arr.length);
System.out.print("数组元素: ");
for (int i = 0; i < arr.length; i++)
System.out.print(" " + arr[i]);
// 操作9
// peek() 方法: 获取头
System.out.println("\n头元素: "
+ de_que.peek());
// 操作10
// poll() 方法: 获取头
System.out.println("头元素poll: "
+ de_que.poll());
// 操作11
// push() 方法
de_que.push(265);
de_que.push(984);
de_que.push(2365);
// 操作12
// remove() 方法: 获取头
System.out.println("头元素删除: "
+ de_que.remove());
System.out.println("最终的数组是: " + de_que);
}
}
输出:
元素:10
元素:20
元素:30
元素:40
元素:50
使用clear()
上面的元素现在已被删除
使用迭代器的双端队列元素:
291
564
24
14
以相反顺序的双端队列元素:
14
24
564
291
使用element()获取头元素:291
使用getFirst()获取头元素:291
使用getLast()获取最后一个元素:14
数组大小:4
数组元素:291 564 24 14
头元素:291
轮询头元素:291
删除头元素:2365
最终数组为:[984, 265, 564, 24, 14]
如果这个例子的清晰度有些滞后,那么我们建议在ArrayDeque类中提出不同的操作。让我们看看如何执行一些经常使用的操作ArrayDeque,以更好地理解我们上面使用的操作来说明整个Array Deque。
- 添加操作
- 访问操作
- 删除操作
- 遍历Deque
让我们通过提供干净的Java程序并同时实现每个操作来详细了解每个操作如下:
操作1: 添加元素
为了将元素添加到ArrayDeque中,我们可以使用add(),addFirst(),addLast(),offer(),offerFirst(),offerLast()方法。
- add()
- addFirst()
- addLast()
- offer()
- offerFirst()
- offerLast()
示例
// Java程序示例:插入元素到ArrayDeque中
//导入所需类
import java.io.*;
import java.util.*;
//主类
//AddingElementsToArrayDeque
public class GFG {
//主程序入口
public static void main(String[] args)
{
//初始化双端队列
//由于Deque是一个接口,
//它被赋予了
//ArrayDeque类
Deque<String> dq = new ArrayDeque<String>();
//使用add()方法插入
dq.add("The");
dq.addFirst("To");
dq.addLast("Geeks");
//使用offer()方法插入
dq.offer("For");
dq.offerFirst("Welcome");
dq.offerLast("Geeks");
//将ArrayDeque元素打印到控制台
System.out.println("ArrayDeque : " + dq);
}
}
输出
ArrayDeque : [Welcome, To, The, Geeks, For, Geeks]
操作2: 访问元素
在添加元素之后,如果我们希望访问元素,则可以使用内置方法如getFirst(),getLast()等。
- getFirst()
- getLast()
- peek()
- peekFirst()
- peekLast()
示例
// Java程序:访问ArrayDeque元素
// 导入所需类
import java.io.*;
import java.util.*;
// 主类
// 访问ArrayDeque元素
public class GFG {
// 主驱动程序
public static void main(String args[])
{
// 创建一个空的ArrayDeque
ArrayDeque de_que
= new ArrayDeque();
// 使用add()方法向Deque中添加元素
// 自定义输入元素
de_que.add("Welcome");
de_que.add("To");
de_que.add("Geeks");
de_que.add("4");
de_que.add("Geeks");
// 显示ArrayDeque
System.out.println("ArrayDeque: " + de_que);
// 显示第一个元素
System.out.println("第一个元素是:"
+ de_que.getFirst());
// 显示最后一个元素
System.out.println("最后一个元素是:"
+ de_que.getLast());
}
}
输出
ArrayDeque: [Welcome, To, Geeks, 4, Geeks]
第一个元素是:Welcome
最后一个元素是:Geeks
操作 3. 删除元素
为了从Deque中删除元素,提供了各种方法。由于我们也可以从两端删除,所以deque接口为我们提供了removeFirst(),removeLast()方法。除此之外,此接口还为我们提供了poll(),pop(),pollFirst(),pollLast()方法,其中pop()用于删除并返回Deque的头部。但是,使用poll()是因为它提供与pop()相同的功能,并且当deque为空时不返回异常。如下所述:
- remove()
- removeFirst()
- removeLast()
- poll()
- pollFirst()
- pollLast()
- pop()
示例
// Java程序:演示Deque中的Removal Elements
// 导入所有实用类
import java.util.*;
// RemoveElementsOfArrayDeque
public class GFG {
// 主驱动程序
public static void main(String[] args)
{
// 初始化Deque
Deque dq = new ArrayDeque();
// add()方法插入
dq.add("One");
// addFirst插入在前面
dq.addFirst("Two");
// addLast插入在后面
dq.addLast("Three");
// 将元素打印到控制台
System.out.println("ArrayDeque : " + dq);
// 删除元素作为堆栈从顶部/前面
System.out.println(dq.pop());
// 将元素作为队列从前面删除
System.out.println(dq.poll());
// 从前面删除元素
System.out.println(dq.pollFirst());
// 从后面删除元素
System.out.println(dq.pollLast());
}
}
输出
ArrayDeque : [Two, One, Three]
Two
One
Three
null
操作 4: 遍历Deque
由于Deque可以从两个方向迭代,所以deque接口的迭代器方法提供了从第一个和从后面迭代的两种方法。如下所述:
- remove()
- iterator()
- descendingIterator()
示例
// Java程序来说明迭代Deque的元素
//导入所有的Utility类
import java.util.*;
//主类
//IterateArrayDeque
public class GFG {
//主要驱动方法
public static void main(String[] args)
{
//声明并初始化一个deque
Deque < String > dq = new ArrayDeque < String > ();
//在后面添加元素
//使用add()方法
dq.add("For");
//在前面添加元素
//使用addFirst()方法
dq.addFirst("Geeks");
//在最后添加元素
//使用addLast()方法
dq.addLast("Geeks");
dq.add("is so good");
//使用Iterator接口迭代
//从队列的前面开始
for (Iterator itr = dq.iterator(); itr.hasNext();) {
//打印元素
System.out.print(itr.next() + " ");
}
//新的一行
System.out.println();
//反向迭代队列中的元素
for (Iterator itr = dq.descendingIterator();
itr.hasNext();) {
System.out.print(itr.next() + " ");
}
}
}
输出
Geeks For Geeks is so good
is so good Geeks For Geeks
极客教程