java没有C++STL,但是有 Stack
类、Deque
接口。
Deque接口是什么?是JDK官方推荐的 Stack
的替代品。
先放一张关系图,方便阅读理解。
替代原因是:
Stack
性能低。Stack
继承自Vector
, 而Vector
在每个方法中都加了锁,保证线程安全,但是Vector
被淘汰掉了,保证线程安全有更优的替代品。Stack
破坏了原有的数据结构。栈的定义是在一端进行push
和pop
操作,除此之外不应该包含其他 入栈和出栈 的方法,但如上所述,Stack
继承自Vector
,使得Stack
可以使用父类Vector
公有的方法,如下所示⬇️⬇️⬇️
val stack = Stack<Int>()
stack.push(6)
stack.add(1,10)
stack.removeAt(1)
stack.pop()
stack.addAll(arrayListOf())
......
但是在网上看一些题解的时候,stack还是很常见,原因是:
- 在做算法题的时候,关注点在解决问题的算法逻辑思路上,并不会关注在不同语言下
Stack
实现细节,但是对于使用 Java 语言的开发者,不仅需要关注算法逻辑本身,也需要关注它的实现细节 - JDK 官方是不推荐使用
Stack
,之所以还有很多人在使用,是因为 JDK 并没有加deprecation
注解,只是在文档和注释中声明不建议使用,但是很少有人会去关注其实现细节
如果只是单纯做算法题,还是可以像其他语言类似地使用stack,但是写工程项目或者写追求更优性能的代码话,建议使用Deque
接口。
下面分别说明基本用法:
➡️Stack类:
1.创建
Stack<Integer> stack = new Stack<>();
2.添加元素
stack.push(1);
stack.push(2);
stack.push(3);
3.删除栈顶元素
int top = stack.pop();
4.获取栈顶元素
int top = stack.peek();
5.获取栈的长度
int length = stack.size();
6.判断栈是否为空
boolean isEmpty = stack.isEmpty();
7.遍历
while(!stack.isEmpty()) {
int top = stack.pop();
}
➡️Deque接口:
实现类有ArrayDeque
(底层采用数组存储)和 LinkedList
(底层采用链表存储),如何选择?
从效率上看,ArrayDeque
会略胜一筹,不过差别通常可以忽略。
但当你插入的对象有可能会为null的情况,只能采用LinkedList
来实现栈。ArrayDeque
的插入操作都是不支持插入为null对象,否则会报NullPointerException异常❗❗❗
1.创建
Deque<Integer> stack = new ArrayDeque<>();
Deque<Integer> stack = new LinkedList<>();
2.添加元素
stack.push(1); //⭐头部
stack.push(2);
stack.push(3);
stack.pushFirst(); //从头部添加
stack.pushLast(); //从尾部添加
3.删除栈顶元素
int top = stack.pop(); //⭐头部
int top = stack.pollFirst(); //从头部删除
int top = stack.pollLast(); //从尾部删除
4.获取栈顶元素
int top = stack.peek(); //⭐头部
int top = stack.peekLast()
5.获取栈的长度
int length = stack.size();
6.判断栈是否为空
boolean isEmpty = stack.isEmpty();
7.遍历
while(!stack.isEmpty()) {
int top = stack.pop();
}
这里注意常用的push,pop,peek都是从头部端实现的。