java数据结构 -- Stack源码解析

1、栈初识

Stack类是jdk中java.util包下的一个类。其方法有
Stack类的方法
栈是一种用于存储数据的简单数据结构,与普通的线性表不同,线性表是先进先出,即FIFO,但是栈是先进后出,即FILO。我们一般只能对栈顶元素进行操作。

2、Stack类的继承关系接口实现

继承与接口实现
Stack继承了Vector类,Vector类又实现了List接口。

3、Stack类的特点

3.1 构造函数

从源码中了解到,Stack类只有一个无参构造函数

    /**
     * Creates an empty Stack.
     */
    public Stack() {
    }

所以,我们无法像ArrayList或者HashMap那样,初始化指定栈的容量大小。那么栈的初识化容量是多少呢?什么时候进行扩容呢?扩容的默认容量是多少呢?
由于Stack继承了Vector类,在Vector类的源码中可以看出:

    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }
    
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }

    public Vector() {
        this(10);
    }

可以看到,如果我们不指定vector的容量大小,那么初始化的默认容量就是10。这和ArrayList的初始化容量一致。
那么何时扩容呢?Stack的push()方法如下

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

        return item;
    }

Stack直接调用了Vector类的addElement(E item)方法

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

private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

可以看到,是在计算插入数据后容量大小与原来容量大小做比较,除非栈满了,才会进行扩容。扩容调用的就是grow(minCapacity)

 private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

可以看到,如果没有指定每次扩容的容量大小,默认的新容量将会是两倍的旧容量。
这一点与我们熟知的ArrayList的扩容大小不一样,ArrayList的新容量大小是旧容量加上旧容量的值的值右移一位。即
n e w C a p a c i t y = o l d C a p a c i t y + ( o l d C a p a c i t y > > 1 ) newCapacity=oldCapacity+(oldCapacity>>1) newCapacity=oldCapacity+(oldCapacity>>1)

3.2 pop与peek

 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);
    }

这两个方法都加锁了,是线程安全的操作。
pop操作当中包含了peek操作,pop是返回栈顶元素,并将该元素从栈中删除。而peek只返回栈顶元素,不删除。
栈的底层数据结构用的是数组。

4、应用

栈的一些应用主要就是运用其先进后出的特性,比较典型的应用就是表达式计算,包括中缀表达式、后缀表达式以及符号匹配等等。
先留个坑,有空再填。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值