携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情
概述
Stack是jdk1.0中引入的一个容器,它是栈的数据结构,最大的特点就是后进先出。实际上jdk发展到如今,已经越来越少的程序员使用该类,更多的是使用ArrayDeque这个功能更加强大、性能更佳的容器。那Stack和ArrayDeque比起来有什么缺点呢?
Stack介绍
Stack类表示一个后进先出(LIFO)的堆栈,当第一次创建堆栈时,它不包含任何项。
以上是Stack的类图, 它继承了Vector这个容器,说明里面的方法也是线程安全的。
构造方法:
- public Stack()
说明:创建一个空的栈
关键方法:
- public E push(E item)
说明:向栈顶添加一个元素
- public synchronized E pop()
说明:从栈顶弹出一个元素
- public synchronized E peek()
说明:查看栈顶元素的内容
- public boolean empty()
说明:查看栈是否为空
- public synchronized int search(Object o)
说明:搜索栈,返回元素在栈中的距离栈顶的位置,如果没有找到返回 -1
使用案例
public class StackTest {
@Test
public void testStack() {
Stack<String> stack = new Stack<>();
stack.push("alvin");
stack.push("cxw1");
stack.push("cxw2");
stack.push("cxw");
stack.push("kk");
String peek = stack.peek();
Assert.assertEquals(peek, "kk");
String pop = stack.pop();
Assert.assertEquals(pop, "kk");
int index = stack.search("cxw");
Assert.assertEquals(index, 1);
}
}
源码解析
- push方法
// 向栈中添加元素
public E push(E item) {
// 调用父类添加元素
addElement(item);
return item;
}
// 同步方法,添加元素
public synchronized void addElement(E obj) {
modCount++;
// 确认底层的数组是否需要扩容,如果需要进行扩容
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
- pop方法
// 栈顶取出元素
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
// 移除一个元素
removeElementAt(len - 1);
return obj;
}
// 查看数组最后一个元素
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
Stack总结
Stack 是 JDK 1.0 的产物,官方已经不推荐使用了。基于 Vector 实现的栈 Stack。底层实际上还是数组,所以还是存在需要扩容。Vector 是由数组实现的集合类,他包含了大量集合处理的方法。而 Stack 之所以继承 Vector,是为了复用 Vector 中的方法,来实现进栈(push)、出栈(pop)等操作。这里就是 Stack 设计不好的地方,既然只是为了实现栈,不用链表来单独实现,而是为了复用简单的方法而迫使它继承 Vector,Stack 和 Vector 本来是毫无关系的。这使得 Stack 在基于数组实现上效率受影响,另外因为继承 Vector 类,Stack 可以复用 Vector 大量方法,这使得 Stack 在设计上不严谨。
所以建议使用ArrayDeque这样的容器来实现栈的功能。