java集合系列之Stack

作者: 愚公要移山 | 来源:发表于2019-07-30 10:20 被阅读2次

    这篇文章开始介绍Stack。从名字看他就是一个stack,因此具有数据结构中栈的一般特性(后进先出),平时用起来相对较多一点,但是也是非常简单。这篇文章我们将从源码的角度来分析一下Stack。

    OK,开始今天的文章。

    一、认识Stack

    Stack继承自Vector。底层是通过数组实现的。下面我们认识一下Stack在整个java集合体系中的位置:

    1-java集合框架.jpg

    我们会发现,其实Stack就是继承自Vector,因此它具有Vector的一般特点。我们把Stack放大,从Stack的角度来看一下:

    2-继承关系.jpg

    从上图我们可以看到,Stack其实就是继承了Vector,Vector具有的接口的父类,Stack也有。

    继承了AbstractList、实现了Enumeration、List、ListIterator等接口。

    下面我们再来看一下源码,它的源码那是超级简单。
    二、源码分析

    一下源码基于jdk1.8来分析的。

    (1)构造方法

    public Stack() {}
    

    只有一个无参构造方法。

    (2)增加元素

    public E push(E item) {
            addElement(item);
            return item;
    }
    

    这里面调用了addElement方法,我们追踪进去,继续往里看

    public synchronized void addElement(E paramE) {
        this.modCount += 1;
        ensureCapacityHelper(this.elementCount + 1);
        this.elementData[(this.elementCount++)] = paramE;
    }
    

    synchronized 说明了这是一个线程安全的方法,他分了三步走的战略:

    • 第一步:它在添加元素的时候首先将modCount加1,保证线程安全。
    • 第二步:ensureCapacityHelper()主要用于保障Stack的容量,在合理范围
    • 第三步:真正实现元素的添加,将该元素添加到栈顶,数目加1;

    (3)删除元素

    public synchronized E pop() {
        E  obj;
        int  len = size();
        obj = peek();
        removeElementAt(len - 1);
        return obj;
    }
    

    在这里我们发现,真正实现删除操作的是removeElementAt;我们追踪进去:

    public synchronized void removeElementAt(int paramInt) {
        this.modCount += 1;
        if (paramInt >= this.elementCount)
          throw new ArrayIndexOutOfBoundsException(paramInt + " >= "
              + this.elementCount);
        if (paramInt < 0)
          throw new ArrayIndexOutOfBoundsException(paramInt);
        int i = this.elementCount - paramInt - 1;
        if (i > 0)
          System.arraycopy(this.elementData, paramInt + 1, this.elementData,
              paramInt, i);
        this.elementCount -= 1;
        this.elementData[this.elementCount] = null;
    }
    

    synchronized 说明了这是一个线程安全的方法,删除操作就有点复杂了,没关系我们继续分析:

    • 第一步:它在添加元素的时候首先将modCount加1,保证线程安全。
    • 第二步:第一个if判断删除元素是否超出了存储的数量范围
    • 第三步:第二个if判断待删除的元素下标大于0
    • 第四步:第三个if将元素后移
    • 第五步:将数量减小1
    • 第六步:将最上面的元素置为空,也就是删除了元素。

    (4)查找操作

    在上面删除的时候我们发现了其实有一个peek()方法我们没有将,他的作用就是返回stack中最顶端的元素。

    public synchronized E peek() {
            int  len = size();
            if (len == 0)
                throw new EmptyStackException();
            return elementAt(len - 1);
    }
    

    但是还有一个最正式的查找操作:

    public synchronized int search(Object o) {
            int i = lastIndexOf(o);
            if (i >= 0) {
                return size() - i;
            }
            return -1;
    }
    

    该方法返回所查找对象所处的位置,如果不存在在返回-1;

    • 第一步:通过lastLindexOf(Object)方法返回从栈底到栈顶最下面的的那个元素的下标,
    • 第二步:利用元素的总数目减去所处的下标就得到了元素的位置(),并且返回否则返回-1;

    (5)其他方法

    这里提供的其他方法只有一个判断是否为空

    public boolean empty() {
        return (size() == 0);
    }
    

    以上就列出了Stack的所有源码,超级简单。最后我们就来对它进行有一个总结

    三、总结

    stack是继承自Vector,底层使用数组存储、用来模拟栈的一个java集合。同时也是线程安全的。使用场景比如说倒序输出、XML语法检查。最主要的是面试还经常使用到它,因此你主要还是在机试的时候灵活的去使用它。

    宣传页_副本2_副本.jpg

    相关文章

      网友评论

        本文标题:java集合系列之Stack

        本文链接:https://www.haomeiwen.com/subject/rergrctx.html