1.概述
- Vector是一个支持集合元素读写、且大小可变、且线程安全、最后还支持“随机访问”特性的List性质的集合。
- 它与ArrayList一样底层都是基于数组的,能进行动态扩容,是早期的线程安全的动态数组版本
- 可以看它与ArrayLlist一样也继承于 AbstractList,实现了 List,RandomAccess,Cloneable, java.io.Serializable 这些接口。
关于这些接口的说明,在ArrayList的讲解中有说明,此处不再赘述
2.源码剖析
2.1 成员变量
/**
* 底层使用的数组
*
*/
protected Object[] elementData;
/**
* Vector中实际保存元素的个数
*/
protected int elementCount;
/**
* 扩容增量
*
* 当这个字段的值为0的时候,默认采用2倍扩容,否则每次扩容的增量为这个字段的值
*/
protected int capacityIncrement;
- 这里专门强调一下capacityIncrement这个字段,没读过源码的人,可能道听途说Vector默认采用2倍扩容,但实际上这个默认很有分量,这里的默认并不是说你不手动调用扩容就采用2倍扩容,而是你不手动调用扩容的话,并且扩容增量小于等于0时,才采用2倍扩容,如果扩容增量大于0,就采用扩容增量进行扩容
2.2 构造函数
/**
* Vector是直接在构造方法中就创建了数组,
*/
public Vector(int initialCapacity, int capacityIncrement) {
super();
//参数检查
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//创建数组
this.elementData = new Object[initialCapacity];
//设置扩容增量
this.capacityIncrement = capacityIncrement;
}
/**
* 只传入容量的话,扩容增量默认为0
*/
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
/**
* 不传入任何参数的话,数组长度默认为10,扩容增量为0
*/
public Vector() {
this(10);
}
/**
* 通过将集合中数据转换成数组,创建一个新的数组,并把数据复制到其中
*
*/
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的时候,不传入初始容量的话,默认容量为10,不传入扩容增量的话,默认扩容增量为0,即Vector采用2倍扩容
- 当Vector的调用默认构造方法的时候,在构造方法中就创建了容量为10的数组
2.3 添加元素
3.Vector与ArrayList对比
相同点:
- 1.两者都是基于索引的,都是基于数组的,在创建数组时,默认容量都为10
- 2.两者都维护插入顺序,我们可以根据插入顺序来获取元素。
- 3.ArrayList 和 Vector 的迭代器实现都是 fail-fast 的。
- 4.ArrayList 和 Vector 两者允许 null 值,也可以使用索引值对元素进行随机访问。
区别:
- 1.同步性:Vector 是线程安全的,也就是说是同步的 ,所有方法均使用synchronized来进行修饰,而 ArrayList 是线程不安全的,不是同步的。
- 2.数据增长:
- Vector当中有个字段capacityIncrement,这个字段我们可以在构造方法中传入,如果扩容的时候,这个小于等于0,默认才会采用2倍扩容
- 而ArrayList 就是确定的1.5倍扩容,并不存在capacityIncrement字段
- Vector当中有个字段capacityIncrement,这个字段我们可以在构造方法中传入,如果扩容的时候,这个小于等于0,默认才会采用2倍扩容
- 3.调用默认构造方法时数组的创建时机:
- Vector在调用默认构造函数的时候在函数内就创建了数组
- jdk1.8的ArrayLilst在调用默认构造方法的时候采用了延迟创建的策略,在构造函数中仅仅是赋予了空数组{},真正创建数组是在第一次调用add方法的时候