从零开始的Java容器学习(四):Vector和Stack

前言

今天我们来学学Vector和Stack这两个“过时”的容器,虽然实际开发过程中用到的可能性不高,但为了List容器的完整性,学一学了解一下还是有必要的。学之前需要回忆一下栈Stack这一数据结构。

Vector和Stack的简要介绍

Vector是基于synchronized实现的线程安全的ArrayList,但在插入元素时容量扩充的机制和 ArrayList稍有不同,并可通过传入 capacityIncrement 来控制容量的扩充。Stack基于Vector 实现,支持LIFO

从这一图可清晰看到Vector继承自AbstractList,实现了List、RandomAccess、Serializable、Cloneable等接口,Stack直接继承Vector。

从源码分析Vector和Stack

成员变量

protected Object[] elementData;//实际是这个数组在存
protected int elementCount;//容器内的元素数量
protected int capacityIncrement;//容器每次扩容增加的量,如不指定则每次两倍扩容
复制代码

构造方法

public Vector(int initialCapacity) {//指定初始大小
        this(initialCapacity, 0);
    }
public Vector() {//如果不指定则默认初始大小为10
        this(10);
    }
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(Collection<? extends E> c) {
    elementData = c.toArray();
    elementCount = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
复制代码

Vector的四种构造方法如上,Stack的构造方法是空参,直接调用父类的空参构造,即默认大小为10.

添加

//
public synchronized boolean add(E e) {//可以看到是通过synchronized来保证线程安全
    modCount++;
    ensureCapacityHelper(elementCount + 1);//确保容量够
    elementData[elementCount++] = e;//在数组尾添加元素
    return true;
}
复制代码

删除

public boolean remove(Object o) {
        return removeElement(o);
    }
public synchronized boolean removeElement(Object obj) {
    modCount++;
    int i = indexOf(obj);
    if (i >= 0) {
        removeElementAt(i);
        return true;
    }
    return false;
}
public synchronized void removeElementAt(int index) {
    modCount++;
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                 elementCount);
    }
    else if (index < 0) {
        throw new ArrayIndexOutOfBoundsException(index);
    }
    int j = elementCount - index - 1;
    if (j > 0) {
        System.arraycopy(elementData, index + 1, elementData, index, j);
    }//使用arraycopy将后面的直接拼接到原数组,直接覆盖要删除的元素
    elementCount--;
    elementData[elementCount] = null; /* to let gc do its work *///然后释放最后一个元素
}
复制代码

更新和查询

set和get比较简单就不细写了

E set(int index, E element);//用指定的元素替换此Vector中指定位置的元素。 
E get(int index);//返回此向量中指定位置的元素。 
复制代码

Stack部分

E peek();//查看此堆栈顶部的对象,而不从堆栈中删除它。 
E pop();//删除此堆栈顶部的对象,并将该对象作为此函数的值返回。 
E push(E item);//将项目推送到此堆栈的顶部。 
复制代码

总结

相比List中另外两个,Vector是线程安全的,以及Vector扩容默认是2倍扩容,默认初始大小则都是10。因为是通过synchronized实现的线程安全,所以效率低。

自此List部分告一段落,下一部分将学习容器的重点Map,包括HashMap、HashTable、LinkedHashMap、TreeMap。

猜你喜欢

转载自juejin.im/post/5ec0ac30e51d454dae55874e