聊一聊Vector与Stack

作者: 姜康 | 来源:发表于2018-03-27 12:28 被阅读250次

Java Collection系列下面有List,Set,Queue等,而Vector属于List下面的一个实现。

特点

  • Vector本质上是一个可变数组
  • 在Vector创建之后,其size可以增加和减少
  • 线程安全的
  • 在非多线程的情况下建议使用ArrayList

简要分析

先看一下有哪些重要的属性:

protected Object[] elementData;
protected int elementCount;
protected int capacityIncrement;

这其中elementData是一个数组,用来实际存储数据;
容量方面有两个概念,一个是elementCount,一个是capacityIncrement;
其中elementCount代表的是中有效元素的个数,也就是说从elementData[0]到elementData[elementCount - 1]中的是实际的数据项。
而capacityIncrement代表的是,当你需要扩容的时候,一次性增加的容量大小。比如,在你向Vector中插入大量数据之前,可以增加capacityIncrement用来减少大量的扩容操作。

扩容机制

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

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

实际扩容的时候,调用的是grow方法。
如果 capacityIncrement > 0 ,则容量新增capacityIncrement大小;
如果 capacityIncrement <=0 , 则容量新增一倍;
然后再对最小应该满足的容量,和最大的容量配置进行判断,保证稳定性。

其中还有一个方法,可以直接设置容量:

 public synchronized void setSize(int newSize) {
        modCount++;
        if (newSize > elementCount) {
            ensureCapacityHelper(newSize);
        } else {
            for (int i = newSize ; i < elementCount ; i++) {
                elementData[i] = null;
            }
        }
        elementCount = newSize;
    }

如果新容量 > 当前的容量,则进行扩容,然后将null元素添加到Vector后面;
如果新容量 <= 当前的容量,则从索引值为newSize的开始,后面的元素全部设置为null;

说完了Vector,就顺便说一下Stack吧。

Stack

Stack继承自Vector,在其基础之上添加了一些入栈,出栈的操作,如push()/pop()/peek()等。

其也是线程安全的;

public
class Stack<E> extends Vector<E> {

    public Stack() {
    }

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

        return item;
    }

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

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

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

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

    private static final long serialVersionUID = 1224463164541339165L;
}


从Stack的源码中可以看到,它的入栈,出栈,查询操作均是利用Vector中的实现方法,并且都是同步的,因此是线程安全,但是性能是有所损耗。

通常可以利用Deque或者Deque的实现类来替换Stack,比如:

Deque<Integer> stack = new ArrayDeque<Integer>();

其中ArrayDeque并非线程安全的,这一点在使用的时候得注意,而且它不支持null元素。

ArrayDeque可以用来作为栈或者队列:

用作Stack的时候,它比Stack快;
用作Queue的时候,它比LinkedList(LinkedList本身实现了Deque接口,因为可以作为Queue来使用)快;

公众号

相关文章

  • 聊一聊Vector与Stack

    Java Collection系列下面有List,Set,Queue等,而Vector属于List下面的一个实现。...

  • 如何优雅地在Stack Overflow提问?

    今天来给大家聊一聊 Stack Overflow,Stack Overflow 是什么呢? 什么是 Stack O...

  • java栈empty()和isEmpty()的区别

    empty()方法是Stack中的成员方法 isEmpty是Vector中的方法,Stack继承了Vector 结...

  • JAVA集合类

    Vector,BitSet,Stack,Hashtable

  • C++ 容器浅析

    vector stack queue list set vector 向量(Vector)是一个动态大小数组的顺序...

  • Java集合Stack源码深入解析

    概要 学完Vector了之后,接下来我们开始学习Stack。Stack很简单,它继承于Vector。学习方式还是和...

  • 聊一聊编码与乱码

    认识几种编码方式ASCII计算机发明之后需要使用0和1来表示字符,于是美国人在50年代发明了 ASCII (美国标...

  • 聊一聊PPI与CPI

    PPI是工业生产者出厂价格指数,CPI是居民消费价格指数。由于CPI反映的主要是日常消费品价格的变动水平,人们都对...

  • 聊一聊 喝水与致癌

    以前我们喝井水,有人说不卫生,有各种细菌?于是我们改喝消过毒的自来水。 于是又有人说,消过毒的自来水含有氯等致癌物...

  • 聊一聊癌症与肿瘤

    在我们生活中,癌症就是肿瘤,肿瘤就是癌症。这两个概念基本不分家。但往细的说,这两个概念也是有差别的。 那我们先看一...

网友评论

    本文标题:聊一聊Vector与Stack

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