Vector
一、简介
Vector底层的数据结构是 “数组”,它会随着元素的增加而动态扩容,它是有序可重复、线程安全的集合,可存入多个 null 对象。Vector 是线程安全版的 ArrayList,它的基本增删改查操作方法都用 Synchronized 修饰。
1.1 源码分析
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}
从源码分析,Vector 继承于 AbstractList,实现了 List,RandomAccess,Cloneable 和 Serializable 接口:
-
实现 List,并继承 AbstractList,获得集合接口 List 的基础功能;
-
实现 RandomAccess ,获得了快速随机访问存储元素的功能(RandomAccess 是一个标记接口,没有任何方法);
// Collections类 public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) { if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD) return Collections.indexedBinarySearch(list, key); else return Collections.iteratorBinarySearch(list, key); } /** *区别: * 实现RandomAccess接口的List集合采用一般的for循环遍历,而未实现这接口则采用迭代器。 * Vector用for循环遍历比iterator迭代器遍历快,LinkedList用iterator迭代器遍历比for循环遍历快。 */
-
实现 Cloneable,重写 clone,实现克隆功能;
-
实现 Serializable,可被序列化。
1.2 使用建议
当集合中有多线程对集合元素进行操作时候,则使用 Vector。但是现在 Vector 一般不再使用,如需在多线程下使用,可以用 java.util.concurrent.CopyOnWriteArrayList。
二、特点
2.1 初始化 Vector 的大小,未指定时默认是10
// 默认初始容量:10
public Vector() {
this(10);
}
// 容量最大值:2147483647
Integer.MAX_VALUE
2.2 数据都存储在数组中
// 未加 transient,序列化时会记录elementData
protected Object[] elementData;
// 是动态数组的实际大小
protected int elementCount;
// 是动态数组的增长系数,默认为0(每次扩容为原大小的两倍)。
protected int capacityIncrement;
2.3 扩容
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
private void ensureCapacityHelper(int minCapacity) {
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
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) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
public Vector() {
this(10);
}
默认构造函数初始化大小为10的数组,设定每次扩容为原来大小的两倍。
不断存入元素会不断扩容,当 newCapacity 扩容量大于数组定义的最大阀值时,会调用 hugeCapacity 进行判断。如果待扩容大小已经超过 Integer 的最大值(溢出为负数),将抛出 OutOfMemoryError (内存溢出错误)。否则返回 Integer的最大值或 MAX_ARRAY_SIZE。故 Vector 的最大容量是 Integer 的最大值(-2的31次方~2的31次方减1)。
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
- 当传入值 < 0 时,会抛出 IllegalArgumentException 异常;
- 当传入值 ≧ 0 时,会创建指定容器大小的数组,设定每次扩容为原来大小的两倍。
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;
// 若elementData存储的是Object的子类,那么不做单独拷贝
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
因为数据存储在数组中,有些虚拟机会在数组对象中额外存储一些信息(如描述对象状态的信息、对象是否同步的信息、数组的大小等),单独判断一次是为了避免内存溢出。