1、概览
本篇,我们将介绍ArrayDeque的使用方法-ArrayDeque是Deque的一个实现。ArrayDeque俗称数组双端队列,是一种允许我们从俩端进行存取操作的可扩容数组。
ArrayDeque既可以作为Stack使用(Last-In-First-Out) 又可以作为Queue使用(First-In-First-Out)。
2、API
针对于每个操作,我们基本上都有俩个可选择的API,第一组API方法在操作失败时,会抛出异常。另一组则会返回一个状态或一个值。
操作 | API | API(会抛出异常) |
---|---|---|
从头部插入元素 | offerFirst(e) | addFirst(e) |
从头部移出元素 | pollFirst(e) | removeFirst(e) |
从头部获取元素 | peekFirst(e) | peekFirst(e) |
从尾部插入元素 | offerLast(e) | addLast(e) |
从尾部移出元素 | pollLast(e) | removeLast(e) |
从尾部获取元素 | peekLast(e) | peekLast(e) |
3、使用方法
下面,我们将通过几个示例来看一下ArrayDeque的用法。
3.1 ArrayDeque作为栈使用
接下来,我们把ArrayDeque当做Stack用-并向其中push一个元素
public static void whenPush_addsAtFirst(){
Deque stack = new ArrayDeque<>();
stack.push("first");
stack.push("second");
System.out.println(stack.getFirst());
}
当用作Stack时,我们如何从中pop出一个元素:
public static void whenPop_removesLast(){
Deque stack = new ArrayDeque<>();
stack.push("first");
stack.push("second");
System.out.println(stack.pop());
}
当stack为空时,pop方法会抛出NoSuchElementException异常。
3.2 ArrayDeque作为队列使用
接下来,我们看把ArrayDeque当做Queue使用时,如何向其中添加一个元素:
public static void whenOffer_addsAtLast(){
Deque queue = new ArrayDeque<>();
queue.offer("first");
queue.offer("second");
System.out.println(queue.getLast());
}
当把ArrayDeque作为Queue使用时,如何从队列中获取元素:
public static void whenPoll_removesFirst(){
Deque queue = new ArrayDeque<>();
queue.offer("first");
queue.offer("second");
System.out.println(queue.poll());
}
若队列为空的话,poll方法将返回null值。
4、ArrayDeque的实现原理
ArrayDeque的底层是由一个数组来实现的,这个数组会在其塞满的时候,把容量扩大一倍。该数组初始化大小为16,它通过维护俩个指针:head、tail实现了双端队列。
4.1 ArrayDeque作为栈的实现原理
正如图上所示,当用户使用push方法向其中添加元素时,它会把head头指针向前移动一位。
当我们从栈中弹出一个元素时,它会把head位置处的元素设置为null(这样的话,此元素就可以被垃圾回收),并且把head指针向后移动一位。
4.2 ArrayDeque作为队列的实现原理
如上图所示,使用offer向队列中添加元素,tail尾指针会向后移动一位。而当用户从队列中拉取一个元素时,它会把head位置处的元素设置为null,并且把head指针向后移动一位。
4.3 ArrayDeque的注意点
最后,有几个注意点我们需要记住:
. ArrayDeque不是线程安全的
. ArrayDeque不能存储Null值
. 相较于同步栈来说,ArrayDeque的速度相当快
. ArrayDeque比LinkedList速度更快
. 大多数操作的时间复杂度都是常数
. ArrayDeque的Iterator是fail-fast的
. 当添加元素时,如果head指针和tail指针指向同一位置,ArrayDeque会自动把容量扩大一倍
5、总结
全部代码如下:
public class ArrayDequeTests {
public static void main(String[] args) throws Exception{
//whenPush_addsAtFirst();
//whenPop_removesLast();
//whenOffer_addsAtLast();
whenPoll_removesFirst();
}
public static void whenPush_addsAtFirst(){
Deque stack = new ArrayDeque<>();
stack.push("first");
stack.push("second");
System.out.println(stack.getFirst());
}
public static void whenPop_removesLast(){
Deque stack = new ArrayDeque<>();
stack.push("first");
stack.push("second");
System.out.println(stack.pop());
}
public static void whenOffer_addsAtLast(){
Deque queue = new ArrayDeque<>();
queue.offer("first");
queue.offer("second");
System.out.println(queue.getLast());
}
public static void whenPoll_removesFirst(){
Deque queue = new ArrayDeque<>();
queue.offer("first");
queue.offer("second");
System.out.println(queue.poll());
}
}
以上就是关于ArrayDeque的简单介绍。
6、参考文献
oracle-javase7-apidoc
baeldung-java-ArrayDeque
stackoverflow-why-is-arraydeque-better-than-linkedlist
java-collections-overview