前言
今天我们来学学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。