Stack容器详解

168 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情

概述

Stack是jdk1.0中引入的一个容器,它是栈的数据结构,最大的特点就是后进先出。实际上jdk发展到如今,已经越来越少的程序员使用该类,更多的是使用ArrayDeque这个功能更加强大、性能更佳的容器。那Stack和ArrayDeque比起来有什么缺点呢?

Stack介绍

Stack类表示一个后进先出(LIFO)的堆栈,当第一次创建堆栈时,它不包含任何项。

以上是Stack的类图, 它继承了Vector这个容器,说明里面的方法也是线程安全的。

构造方法:

  1. public Stack()        

说明:创建一个空的栈

关键方法:

  1. public E push(E item)

说明:向栈顶添加一个元素

  1. public synchronized E pop()

说明:从栈顶弹出一个元素

  1. public synchronized E peek()

说明:查看栈顶元素的内容

  1. public boolean empty()

说明:查看栈是否为空

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