Deque是一个双端队列接口,继承自Queue接口,Deque的实现类是LinkedList、ArrayDeque、LinkedBlockingDeque,其中LinkedList是最常用的。在 Collections API 中有下面两种实现:
java.util.LinkedList
java.util.ArrayDeque
LinkedList类是非常标准的Deque和Queue的实现,它在内部使用链接列表来建模queue或deque。
ArrayDeque类内部存储元素是数组,如果元素数超过数组中的空间,则分配一个新的数组,并移动所有元素,换句话说,ArrayDeque根据需要增长,即使它将元素存储在数组中
一般而言,都会选择LinkedList
,而非ArrayDeque
Deque的三种用途:
普通队列(一端进另一端出):
Queue queue = new LinkedList()或Deque deque = new LinkedList()
双端队列(两端都可进出)
Deque deque = new LinkedList()
堆栈
Deque deque = new LinkedList()
注意:Java堆栈Stack类已经过时,Java官方推荐使用Deque替代Stack使用。Deque堆栈操作方法:push()、pop()、peek()。 |
---|
Deque是一个线性collection,支持在两端插入和移除元素。名称 deque 是“double ended queue(双端队列)”的缩写,通常读为“deck”。大多数 Deque 实现对于它们能够包含的元素数没有固定限制,但此接口既支持有容量限制的双端队列,也支持没有固定大小限制的。
此接口定义在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常
,另一种形式返回一个特殊值
(null 或 false,具体取决于操作)。插入操作的后一种形式是专为使用有容量限制的 Deque 实现设计的;在大多数实现中,插入操作不能失败。
第一个元素(头部) | 最后一个元素(尾部) | |||
---|---|---|---|---|
抛出异常 | 特殊值 | 抛出异常 | 特殊值 | |
插入 | addFirst(e) | offerFirst(e) | addLast(e) | offerLast(e) |
删除 | removeFirst() | pollFirst() | removeLast() | pollLast() |
检查 | getFirst() | peekFirst() | getLast() | peekLast() |
Deque接口扩展(继承)了 Queue 接口。在将双端队列用作队列时,将得到 FIFO(先进先出)行为。将元素添加到双端队列的末尾,从双端队列的开头移除元素。从 Queue 接口继承的方法完全等效于 Deque 方法,如下表所示:
Queue方法 | 等效Deque方法 |
---|---|
add(e) | addLast(e) |
offer(e) | offerLast(e) |
remove() | removeFirst() |
poll() | pollFirst() |
element() | getFirst() |
peek() | peekFirst() |
双端队列也可用作 LIFO(后进先出)堆栈。应优先使用此接口而不是遗留 Stack 类。在将双端队列用作堆栈时,元素被推入双端队列的开头并从双端队列开头弹出。堆栈方法完全等效于 Deque 方法,如下表所示:
堆栈方法 | 等效Deque方法 |
---|---|
push(e) | addFirst(e) |
pop() | removeFirst() |
peek() | peekFirst() |
常用方法
addLast()
该方法可以在Deque的尾部添加元素,这与Deque接口从Queue接口继承的add()方法等效:
Deque<String> deque = new LinkedList<>();
deque.addLast("element 1");
如果Deque中不能添加元素则addLast()方法会抛异常, offerLast()方法则会返回false
addFirst()
该方法可以在Deque的头部添加元素
Deque<String> deque = new LinkedList<>();
deque.addFirst("element 1");
如果Deque不能添加元素,addFirst()方法会抛异常, offerFirst()方法则返回 false
push()
push可以在Deque的头部添加元素,效果等同于addFirst()
Deque<String> deque = new LinkedList<>();
deque.push("element 0");
pop()
该方法将移除Deque的头部元素,如果Deque是空则报异常
Deque<String> deque = new LinkedList<>();
deque.add("element 0");
deque.add("element 1");
deque.add("element 2");
String removedElement = deque.removeLast();
peekFirst()
该方法返回Deque的第一个元素,如果Deque是空则返回NULL,不会报异常,同时,它不会破坏Deque结构,只是单纯返回一个值而已
Deque<String> deque = new LinkedList<>();
deque.add("first element");
deque.add("last element");
String firstElement = deque.peekFirst();
peekLast()
该方法与peekFist()相反,它会返回Deque的最后一个元素,同样不会破获其结构,不会报异常
Deque<String> deque = new LinkedList<>();
deque.add("first element");
deque.add("last element");
String firstElement = deque.peekLast();
getFirst()
同peekFirst,获取Deque的第一个元素并且保持Deque结构,但是当Deque为空时,会报异常
Deque<String> deque = new LinkedList<>();
deque.add("first element");
deque.add("last element");
String firstElement = deque.getFirst();
removeFirst()
该方法将删除Deque的头部元素,如果Deque为空则报异常
Deque<String> deque = new LinkedList<>();
deque.add("element 0");
String removedElement = deque.removeFirst();
removeLast()
该方法将删除Deque的尾部元素,如果Deque为空则报异常
Deque<String> deque = new LinkedList<>();
deque.add("element 0");
deque.add("element 1");
deque.add("element 2");
String removedElement = deque.removeLast();
pollFirst() / pollLast()
这两方法和 removeFirst / removeLast 的效果是一样的,只不过,当Deque为空时,不报异常,而是返回NULL
Deque<String> deque = new LinkedList<>();
deque.add("element 0");
deque.add("element 1");
deque.add("element 2");
String removedElement = deque.pollFirst();
String removedElement = deque.pollLast();
检查Deque是否包含某个元素
可以用contains()方法检查Deque中是否包含某个元素,如果包含返回true否则返回false:
Deque<String> deque = new ArrayDeque<>();
deque.add("first element");
boolean containsElement1 = deque.contains("first element");
boolean containsElement2 = deque.contains("second element");
通过For-Each循环迭代Deque
Deque<String> deque = new LinkedList<>();
deque.add("element 0");
deque.add("element 1");
deque.add("element 2");
for(String element : deque) {
System.out.println(element);
}