概述
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这样的容器来实现栈的功能。