Java数据结构——Stack和父类Vector

本文探讨了Java数据结构中的Stack和Vector。Stack作为基于List的先进后出(FILO)结构,继承自Vector。Vector与ArrayList虽然相似,但Vector的所有操作是线程安全的,而ArrayList不是。此外,Vector在扩容时会成倍增加数组大小,ArrayList只增加50%。Stack的进栈、出栈和搜索操作基于Vector的基本操作实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

栈是先进后出的结构,JDK中提供的Stack类实现基于List,并使用FILO的方法管理数据。

Stack继承自Vector,本质是一个实现了Collection和List接口的类。Vector是一个古老的java类,在JDK1.0上已经开始支持,它是后来者ArrayList的同源兄弟,在看Stack源码前,先从Vector和ArrayList开始。

Vector和ArrayList的关系和对比

而Vector与ArrayList可谓是兄弟,因为它们的继承关系和实现的接口都是一致的,内部数据同样是通过数组来存储。

public class Vector<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

它们之间最大的不同点有2个:
1. Vector操作数组的方法都是同步的(synchronized),而ArrayList是非线程安全的,效率会比Vector高。
2. Vector在扩容时,数组大小会基于现有的长度成倍增加,而ArrayList只会增加现有长度的50%。

Vector操作数据的方法是同步的

Vector和ArrayList各自的插入方法实现基本是一模一样的,区别还真是只有Vector的方法时synchronized的。

    //Vector的插入方法
    public synchronized void insertElementAt(E obj, int index) {
        ...
        ensureCapacityHelper(elementCount + 1);
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
        elementData[index] = obj;
        elementCount++;
    }

    //ArrayList的插入方法
    public void add(int index, E element) {
        ...
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

Vector与ArrayList扩容方法的对比

    //Vector每次扩容后数组长度都会增加一倍
    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长度只会增加当前大小的一半
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1); //1.5倍
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

Stack类分析

Stack类实现比较简单,方法实现都是基于Vector类已实现的基本操作(插入/删除/访问/修改等),主要时出栈的逻辑以先进后出的逻辑实现。

进栈

将数据放到栈顶,即数组的最后一个元素。

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

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

出栈

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

搜索

搜索方法调用的是Vector中提供的查找方法,从数组尾部开始查找,及返回离栈顶最近的数据位置。

    public synchronized int search(Object o) {
        int i = lastIndexOf(o);

        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }

    //Vector.java
    public synchronized int lastIndexOf(Object o, int index) {
        ...
        if (o == null) {
            ...
        } else {
            for (int i = index; i >= 0; i--) //从数组尾部开始查找
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值