Java下的ArrayDeque、Stack、LinkedList三种数据结构的区别
数据结构
由继承树看出,三者都是Collection的间接实现类。
ArrayDeque实现Deque接口,Stack继承于Vector,LinkedList实现Deque与List接口
底层数据存储方式
存储方式 | |
---|---|
Stack | 长度为10的数组 |
ArrayDeque | 长度为16的数组LinkedList链表 |
LinkedList | 链表 |
线程安全
线程安全 | |
---|---|
Stack | 线程同步 |
ArrayDeque | 线程不同步 |
LinkedList | 线程不同步 |
Deque
Deque是“双端队列的缩写”,Deque接口下都是双向的数据结构,如:LinkedList(链表、栈)、ArrayDeque(双向队列、栈)。二者都具备作为栈的能力。
ArrayDeque
基于数组实现,并且具有作为栈的能力!!!
-
构造方法
ArrayDuque<E> queue = new ArrayDeque<E>();
-
peek() 返回但不删除队头节点的值 等同于peekFirst()
peekFirst(); peek();
-
peekLast() 返回但不删除队末的值
peekLast();
-
add(E e) 进队 在队末加入元素 等同于addLast()
queue.add(e); queue.addLast(e);
-
addFirst(E e) 在队头加入元素
-
clone() 克隆一个相同的队列
ArrayDeque<E> queue2 = queue.clone();
-
isEmpty() 判断是否为空
-
Iterator() 返回这个队列的迭代器
//输出队列所有元素 Iterator<Integer> iterator = mem.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); }
-
remove() 将队头的元素出队 等同于removeFirst()
remove(); removeFirst();
-
removeLast() 将队末的元素出队
removeLast();
-
size() 返回队列的长度
int size = queue.size();
-
toArray() 返回队列所有元素(从头到尾)
E[] arr = queue.toArray();
-
pop() 删除并返回头元素的值
int res = stack.pop();
-
getFirst() 得到头元素
-
getLast() 得到尾元素
Deque / LinkedList的方法使用
必读
==注意:==看似相同的方法区别很大,使用时必须注意,比如add()方法和push()方法截然不同,前者用于构造队列,后者可以用来构造栈,两个方法的效果也不一样!!!
- add 和 remove ** 是一对,源自Collection**;
- offer和poll是一对,源自Queue;
- push和pop是一对,源自Deque,其本质是栈(Stack类由于某些历史原因,官方已不建议使用,使用Deque代替);
- offerFirst / offerLast 和 pollFirst ** / pollLast ** 是一对,源自Deque,其本质是双端队列。
而这些方法出现都在LinkedList / Deque 中,是由于它们的继承关系导致的。尤其需要注意的是:接口Deque是栈和双端队列这两种数据结构的集合体,Deque接口代替了Stack类;
公共方法
这些方法是各种数据结构都可以用的,不需要注意
- size()
- getFirst()
- getLast()
方法
- **add ** / remove源自集合,所以添加到队尾,从队头删除;
- offer / poll源自队列(先进先出 => 尾进头出),所以添加到队尾,从队头删除;
- push / pop源自栈(先进后出 => 头进头出),所以添加到队头,从队头删除;
- offerFirst / **offerLast ** / pollFirst / pollLast源自双端队列(两端都可以进也都可以出),根据字面意思,offerFirst添加到队头,offerLast 添加到队尾,pollFirst从队头删除,pollLast从队尾删除。
- 总结:
add / offer / offerLast 添加队尾,三个方法等价;
push / offerFirst 添加队头,两个方法等价。
remove / pop / poll / pollFirst 删除队头,四个方法等价;
pollLast 删除队尾。
方法选择
虽说某几个方法等价,但是我们在使用的时候,建议根据用途来使用不同的方法,比如你想把 LinkedList 当做集合list,那么应该用add/remove,如果想用作队列,则使用offer/poll,如果用作栈,则使用push/pop,如果用作双端队列,则使用offerFirst/offerLast/pollFirst/pollLast。根据语义使用,就不会发生:我想删队尾,结果删了队头这种事了。
栈
栈的实现可以用Deque(常见的),也可以用LinkedList
- push() 压栈
- pop() 出栈
队列
- offer() 入队
- poll () 出队
双端队列
- offerFirst() 添加到队头
- offerLast () 添加到队尾
- pollFirst () 删除队头
- pollLast () 删除队尾
性能选择
通常情况下,不推荐使用Vector以及其子类Stack
-
频繁的插入、删除操作:LinkedList
-
频繁的随机访问操作:ArrayDeque
-
未知的初始数据量:LinkedList
感觉上,只要底层是数组的就比底层是链表的随机访问效率高,插入删除效率低