简介
Vetcor与ArrayList相似,其内部都是通过一个容量能够动态增长的数组来实现的。不同点是Vector是线程安全的。因为其内部有很多同步代码快来保证线程安全.
JDK中原文有一句注释
Vector is synchronized. If a thread-safe implementation is not needed, it is recommended to use ArrayList in place of Vector
意为“Vector 是同步的。如果不需要线程安全的实现,推荐使用ArrayList代替Vector
特点
- 类似 ArrayList,底层采用可变长Object[]数组存储数据,默认长度为10
- 线程安全,
- 扩容默认增长为原来的 2 倍,还可以指定增长空间长度。
底层实现
底层数据结构
与ArrayList
一样,底层为一个可扩容的数组作为存储结构,
属性
public class Vector<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
//存储元素的数组,初始容量为10
protected Object[] elementData;
//记录数组中元素个数
protected int elementCount;
//capacityIncrement:自动扩容的大小,即当数组满了之后,就添加capacityIncrement个空间装载元素,如果 capacityIncrement<=0,则扩容时就扩容到目前Vector容量的两倍
protected int capacityIncrement;
//该类的序列化版本号
private static final long serialVersionUID = -2767605614048989439L;
//elementData 最大的容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
}
其他方法
ensureCapacity
该方法的实现和ArrayList中大致相同。不同的是在第一次扩容时,vector的逻辑是:
newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
即如果capacityIncrement>0,就加capacityIncrement,如果不是就增加一倍。
而ArrayList的逻辑是:
newCapacity = oldCapacity + (oldCapacity >> 1);
即增加现有的一半。
/**
* 增加vector容量
* 如果vector当前容量小于至少需要的容量,它的容量将增加。
*
* 新的容量将在旧的容量的基础上加上capacityIncrement,除非capacityIncrement小于等于0,在这种情况下,容量将会增加一倍。
*
* 增加后,如果新的容量还是小于至少需要的容量,那就将容量扩容至至少需要的容量。
*
* @param minCapacity 至少需要的容量
*/
public synchronized void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
modCount++;
ensureCapacityHelper(minCapacity);
}
}
/**
* ensureCapacity()方法的unsynchronized实现。
*
* ensureCapacity()是同步的,它可以调用本方法来扩容,而不用承受同步带来的消耗
*
* @see #ensureCapacity(int)
*/
private void ensureCapacityHelper(int minCapacity) {
// 如果至少需要的容量 > 数组缓冲区当前的长度,就进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 分派给arrays的最大容量
* 为什么要减去8呢?
* 因为某些VM会在数组中保留一些头字,尝试分配这个最大存储容量,可能会导致array容量大于VM的limit,最终导致OutOfMemoryError。
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 扩容,保证vector至少能存储minCapacity个元素。
* 首次扩容时,newCapacity = oldCapacity + ((capacityIncrement > 0) ?capacityIncrement : oldCapacity);即如果capacityIncrement>0,就加capacityIncrement,如果不是就增加一倍。
*
* 如果第一次扩容后,容量还是小于minCapacity,就直接将容量增为minCapacity。
*
* @param minCapacity 至少需要的容量
*/
private void grow(int minCapacity) {
// 获取当前数组的容量
int oldCapacity = elementData.length;
// 扩容。新的容量=当前容量+当前容量/2.即将当前容量增加一倍
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) {
//如果minCapacity<0,抛出异常
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//如果想要的容量大于MAX_ARRAY_SIZE,则分配Integer.MAX_VALUE,否则分配MAX_ARRAY_SIZE
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}