java集合之Vector和Stack解析

Vector是线程安全的ArrayList,自JDK1.0开始就有了,而ArrayList是在JDK1.2才开始有的.Vector的也是基于动态数组的,实现逻辑与ArrayList几乎一模一样,主要区别在与增删改查方法上增加了synchronized关键字,用来保障多线程安全.Stack是Vector的唯一子类,用来实现栈操作push/pop,它本质上也是基于数组实现的。

下面是Vector的结构图:


java集合之Vector和Stack解析_第1张图片
vector.jpg
public class Vector extends AbstractList implements List, RandomAccess, Cloneable, Serializable {
    protected Object[] elementData;
    protected int elementCount;
    protected int capacityIncrement;
    private static final long serialVersionUID = -2767605614048989439L;
    private static final int MAX_ARRAY_SIZE = 2147483639;

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

    public Vector(int var1) {
        this(var1, 0);
    }

    public Vector() {
        this(10);
    }

    public Vector(Collection var1) {
        this.elementData = var1.toArray();
        this.elementCount = this.elementData.length;
        if(this.elementData.getClass() != Object[].class) {
            this.elementData = Arrays.copyOf(this.elementData, this.elementCount, Object[].class);
        }

    }

上面的vector同样继承于AbstractList,实现了RandomAccess,Cloneable,Serializable这三个标记接口,默认情况下初始容量也是10,不同于ArrayList的在于多了一个capacityIncrement变量,可以用来指定扩容时容量的增长空间,下面有用到。

Vector中的add操作

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

多了个synchronized修饰符,确保同步安全,调用了this.ensureCapacityHelper确保容量空间是足够的,这里的elementCount相当于ArrayList中的size(可能后来设计ArrayList的时候觉得size比较形象就替换名称了吧)。
private void ensureCapacityHelper(int var1) {
        if(var1 - this.elementData.length > 0) {
            this.grow(var1);
        }

    }

    private void grow(int var1) {
        int var2 = this.elementData.length;
        int var3 = var2 + (this.capacityIncrement > 0?this.capacityIncrement:var2);
        if(var3 - var1 < 0) {
            var3 = var1;
        }

        if(var3 - 2147483639 > 0) {
            var3 = hugeCapacity(var1);
        }

        this.elementData = Arrays.copyOf(this.elementData, var3);
    }

上面的实现与ArrayList一样没什么好说的,区别在于这里如果指定的扩充容量>0,这时扩充的容量是当前数组的容量加上capacityIncrement之和的总量,否则就是把当前容量扩大至当前数组容量的两倍,如果扩容后仍然小于需要的容量,就把当前的容量大小设置为需要的容量,最后复制数组到设定的总容量数组中。

其他的remove,get等方法与Arraylist的实现基本一致,这里不再赘述。


Stack继承与Vector它实现了栈操作,先进后出的思想实现。

public class Stack extends Vector {
    private static final long serialVersionUID = 1224463164541339165L;

    public Stack() {
    }

    public E push(E var1) {
        this.addElement(var1);调用的 Vector.addElement(),添加到尾部
        return var1;
    }

    public synchronized E pop() {
        int var2 = this.size();
        Object var1 = this.peek();调用peek()获取最后一个数据,最后返回
        this.removeElementAt(var2 - 1);删除最后一个数据元素
        return var1;
    }

    public synchronized E peek() {获取Vector中最后一个数据,但不删除
        int var1 = this.size();
        if(var1 == 0) {
            throw new EmptyStackException();
        } else {
            return this.elementAt(var1 - 1);
        }
    }

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

    public synchronized int search(Object var1) {
        int var2 = this.lastIndexOf(var1);
        return var2 >= 0?this.size() - var2:-1;
    }
}

上面的源码实现比较简单,上面出现个序列化版本号,这里简单提下Seriliable是具备继承性的.
完成入栈/出栈操作的思想是:push的时候把数据元素添加到集合尾部,pop的时候获取集合尾部数据并删除,这样就实现了基于动态数组先进后出的逻辑实现。因为LinkList实现了双端队列Deque所以使用LinkList也可以很轻松的完成栈和队列的实现。详情见java集合之LinkList解析

上面的方法除了push没有加synchronized,pop/peek/search都加了synchronized,实现同步操作.

如果没有线程安全的需求,一般推荐使用 ArrayList,而不是 Vector,因为每次都要频繁的获取/释放锁操作,效率比较低。

你可能感兴趣的:(java集合之Vector和Stack解析)