Deque相关方法详解
1 Deque能干什么?
我们在日常开发中经常会用到队列和栈的数据结构在Java中表示队列和栈的有Queue和Stack,而Stack作为Java的丢弃品已经没人用了。而Deque双端队列这种数据结构就很灵活了,即可以满足队列的FIFO特性,又可以满足栈的LIFO特性,那么分别作为队列和栈Deque该如何使用呢?下一小节将详细说明每一个方法。
2 Deque的相关方法
方法 | 说明 |
---|---|
add方法 | 往队列尾部加入元素 |
addFirst方法 | 往队列首部加入元素 |
addLast方法 | 往队列尾部加入元素 |
contains方法 | 判断队列中是否包含某个元素 |
descendingIterator方法 | 以相反的顺序返回deque |
element方法 | 检索但不删除返回队列的头部 |
getFirst方法 | 与element相同,检索但不删除返回第一个元素,具体不知道为什么会有重复的方法,应该是版本更新兼容吧,就语义来说这个好一点 |
getLast方法 | 检索并返回最后一个元素 |
iterator方法 | 以正确的顺序返回此元素的迭代器 |
offer方法 | 将指定元素插入该元素的尾部,返回true或者false,与add的区别是add当没有可用空间时会抛异常,而offer返回false |
offerFirst方法 | 在双端队列头部插入元素 |
offerLast方法 | 在双端队列尾部插入元素,同offer一样,为了Queue和Deque兼容 |
peek()方法和peekFirst/peekLast方法 | 返回但不删除双端队列的首元素/尾元素 |
poll方法和pollFirst/pollLast方法 | poll检索并删除队列的首元素,pollFirst也是,pollLast检索并删除队列的尾元素 |
pop方法 | pop从这个deque表示的堆栈中弹出一个元素,与poll不同的是pop当为空时会报异常,而poll会返回null |
push方法 | 在此deque的首部添加元素 |
remove方法以及removeFirst/removeLast方法 | remove和removeFirst检索并删除队列中第一个元素,removeLast检索并删除队列中最后一个元素(同poll相同,就不演示了) |
size方法 | 返回此的确中的元素数 |
3 代码演示
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
/**
* Created by Yinlu on 2021/7/21
*/
public class DequeTest {
public static void main(String[] args) {
// 测试Deque的每一个方法
Deque<Integer> deque = new LinkedList<>();
// 1. add方法:往队列尾加入元素
/*
下面的三个语句执行完队列如下
头 尾
----------------
1 2 3
----------------
*/
deque.add(1);
deque.add(2);
deque.add(3);
System.out.println(deque); // 1 2 3
// 2. addFirst方法:往双端队列的前面插入一个元素
/*
头 尾
----------------
0 1 2 3
----------------
*/
deque.addFirst(0);
System.out.println(deque); // 0 1 2 3
// 3. addLast方法:往双端队列的尾部插入一个元素,与add的区别就是该方法没有返回值,而add成功时会返回true
deque.addLast(4);
System.out.println(deque); // 0 1 2 3 4
// 4. contains方法:判断队列中是否包含某个元素
boolean contains = deque.contains(3);
System.out.println(contains); // true
// 5. descendingIterator方法:以相反的顺序返回deque的迭代器
Iterator<Integer> iterator = deque.descendingIterator();
while (iterator.hasNext()){ // 打印出4 3 2 1 0
System.out.print(iterator.next() + " ");
}
System.out.println();
// 6. element方法:检索但不删除返回队列的头部
Integer elem = deque.element();
System.out.println(elem); // 0
// 7. getFirst方法:与element相同,检索但不删除返回第一个元素,具体不知道为什么会有重复的方法,应该是版本更新兼容吧,就语义来说这个好一点
Integer first = deque.getFirst();
System.out.println(first); // 0
// 8. getLast方法:检索并返回最后一个元素
Integer last = deque.getLast();
System.out.println(last); // 4
// 9. iterator方法:以正确的顺序返回此元素的迭代器
Iterator<Integer> iterator1 = deque.iterator();
while (iterator1.hasNext()) {
System.out.print(iterator1.next() + " ");
}
System.out.println();
// 10. offer方法:将指定元素插入该元素的尾部,返回true或者false,与add的区别是add当没有可用空间时会抛异常,而offer返回false
boolean offer = deque.offer(5);
System.out.println(deque); // 0 1 2 3 4 5
// 11. offerFirst方法:在双端队列头部插入元素
deque.offerFirst(-1);
System.out.println(deque); // -1 0 1 2 3 4 5
// 12. offerLast方法:在双端队列尾部插入元素,同offer一样,为了Queue和Deque兼容
deque.offerLast(6);
System.out.println(deque); // -1 0 1 2 3 4 5 6
// 13. peek()方法和peekFirst/peekLast方法:返回但不删除双端队列的首元素/尾元素
Integer peek = deque.peek();
Integer first1 = deque.peekFirst();
System.out.println(peek); // -1
System.out.println(first1); // -1
System.out.println(); // 6
// 14. poll方法和pollFirst/pollLast方法:poll检索并删除队列的首元素,pollFirst也是,pollLast检索并删除队列的尾元素
deque.poll(); // deque中元素变为0 1 2 3 4 5 6
System.out.println(deque);
deque.pollFirst(); // deque中元素变为 1 2 3 4 5 6
System.out.println(deque);
deque.pollLast(); // deque中元素变为 1 2 3 4 5
System.out.println(deque);
// 15. pop方法:pop从这个deque表示的堆栈中弹出一个元素,与poll不同的是pop当为空时会报异常,而poll会返回null
// 演示一下为空时调用pop方法
Deque<Integer> q = new LinkedList<>();
// q.pop(); 抛出Exception in thread "main" java.util.NoSuchElementException异常
// 16. push方法:在此deque的首部添加元素
deque.push(0); // deque中元素变成0 1 2 3 4 5
System.out.println(deque);
// 17. remove方法以及removeFirst/removeLast方法:remove和removeFirst检索并删除队列中第一个元素,removeLast检索并删除队列中最后一个元素(同poll相同,就不演示了)
// 不同的是remove可以删除指定元素第一次出现的元素:remove(Object o) 删除o在队列中第一次的出现。
deque.remove(3);
System.out.println(deque); // 0 1 2 4 5
// 18. size方法:返回此的确中的元素数
int size = deque.size();
System.out.println(size); // 5
}
}
4 总结
由上面API可以看出Deque中实现的很多方法都有重复的语义,应该是Java为了兼容Queue或者Collection接口的方法,不管是因为什么上面的所有方法并不需要全部记得,当然全部记住也容易对初学者产生困惑,因此这里针对队列和栈分别列出使用的方法,我们只需要日常中用以下方法就可以了,至于其他的方法自己就不要写了,看到的话知道是怎么回事就行。
4.1 队列
队列遵循先进先出,因此我们在入队时可以从尾部往头部插入元素,出队时从头部出元素就行。
入队:offer从尾部添加元素,同样的offerLast也有相同语义。
出队:从头部出元素poll,同样的pollFirst也有相同语义。
查看队首:peek方法
4.2 栈
栈遵循后进先出。
入栈:push在双端队列首部添加元素
出栈:poll从队列的首部溢出元素
栈顶:peek方法
注:有时候为了灵活性,我们还要理解offerLast、pollLast、offerFirst、pollFirst方法的含义,比如我们如果要按入队的顺序打印元素,但移除最后一个入队元素这样单纯的队列和栈就不能够满足了,总之我们理解双端队列到底是什么,在纸上画一个双端队列的队首队尾就能对这些方法有个更清晰的认识了。