Java集合的 Vector底层讲解
Vector作为List的另外一个典型的实现类,完全支持List的全部功能,Vector的实现其实和ArrayList的底层实现很类似,都是封装了一个Object[],但Vector是一个比较古老的集合,JDK1.0就已经存在,建议不要使用这个集合,Vector与ArrayList的主要区别是:Vector是线程安全的,ArrayList是非线程安全的,但性能上Vector比ArrayList低。
基本属性
protected Object[] elementData; //存放元素的数组
protected int elementCount; //已经放入数组的元素个数
protected int capacityIncrement; //数组的增长系数
源码解析
package java.util;
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
//定义数组,存放元素
protected Object[] elementData;
//已经放入数组的元素数量
protected int elementCount;
//增长的系数
protected int capacityIncrement;
//可序列化版本号
private static final long serialVersionUID = -2767605614048989439L;
//构造方法,提供初始大小,和增长系数
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(int initialCapacity) {
this(initialCapacity, 0);
}
//无参构造方法
public Vector() {
this(10);
}
//构造方法,将指定的集合元素转化为Vector
public Vector(Collection<? extends E> c) {
elementData = c.toArray();
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
//判断c.toArray是否是Object[]类型
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
//将elementData中的元素全部拷贝到anArray数组中
public synchronized void copyInto(Object[] anArray) {
System.arraycopy(elementData, 0, anArray, 0, elementCount);
}
//将数组长度设置为等于vector的个数
public synchronized void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (elementCount < oldCapacity) {
elementData = Arrays.copyOf(elementData, elementCount);
}
}
//扩充容量
public synchronized void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
modCount++;
ensureCapacityHelper(minCapacity);
}
}
//扩充容量帮助函数
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//扩充容量执行方法
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//根据capacityIncrement进行判断,capacityIncrement> 0 增加capacityIncrement个容量,否则容量扩充当前容量的一倍
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//扩容操作,生成已给新的数组,容量为newCapacity,并将elementData中的元素全部拷贝到新数组中,并将新生成的数组在赋值给elementData
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
总结
Vector和ArrayList的底层实现方式非常的相近,官方说少使用Vector,还是尽量少使用,通过源码可以看出,每个方法都添加了synchronized关键字来保证同步,所以它是线程安全的,但是正是这些方法的同步,让其效率大大的降低了。比ArrayList的效率要慢
因此,给出以下几点总结:
1、Vector有四个不同的构造函数。 无参构造的容量默认值为10
2、扩充容量的方法ensureCapacityHelper。与ArrayList不同的是,Vector在每次增加元素(可能是1个,也可能是一组)时,都要调用该方法来确保足够的容量。当容量不足以容纳当前的元素个数时,就看构造方法中传入的容量增长系数CapacityIncrement是否为0,如果不为0,就设置新的容量为 旧容量 + 容量增长量;如果为0,设置新的容量为旧的容量的2倍,如果设置后的容量还不够,则直接新的容量设置为 旧容量 + 传入参数所需要的容量 而后同样用Arrays.copyof()方法将元素拷贝到新的数组。
3、很多方法都加入了synchronized同步语句,来确保线程安全。
4、Vector在查找给定元素索引值等方法中,源码都将该元素的值分为null和不为null两种情况处理,Vector中允许元素为null
5、其他很多地方与ArrayList实现大同小异,Vector现在已经不再使用。