目录
Vector
类
相比很多同学在刚接触 Java
集合的时候,线程安全的 List
用的一定是 Vector
。但是现在用到的线程安全的 List
一般都会用 CopyOnWriteArrayList
,很少有人再去用 Vector
了,至于为什么,文章中会具体说到。接下来,我们先来简单分析一下 Vector
的源码
Vector
源码
Vector
和 ArrayList
的底层实现是一样的,都是由数组实现的
Vector
变量
public class Vector<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
// 存放元素的数组
protected Object[] elementData;
// 元素个数
protected int elementCount;
// 扩容自增容量大小
protected int capacityIncrement;
}
Vector
的初始化
// 无参构造器
public Vector() {
this(10);
}
// 指定初始化容量的构造器
public Vector(int initialCapacity) {
this(initialCapacity, 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;
}
从上面的构造器中可以看出,如果调用无参构造器,则会创建一个初始化容量为 10
,扩容容量为 0
的 Vector
集合
Vector
的 add()
方法
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
Vector
的 removeElement()
方法
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}
public synchronized void removeAllElements() {
modCount++;
for (int i = 0; i < elementCount; i++)
elementData[i] = null;
elementCount = 0;
}
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
int numMoved = elementCount - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--elementCount] = null; // Let gc do its work
return oldValue;
}
Vector
的 get()
方法
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
Vector
的 set()
方法
public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
Vector
的扩容
Vector
的扩容机制和 ArrayList
的很像
private void grow(int minCapacity) {
// 初始化数组的长度,默认为 10
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);
}
通过上面的方法,我们可以看出,
- 如果指定了扩容容量的大小,则扩容的新数组大小为:原来的数组加上扩容容量的大小
- 如果不指定扩容容量的大小,则扩容的新数组大小为:原来数组大小的
2
倍
这样扩容为原来的 2
倍是很消耗空间的,这也是 Vector
被弃用的原因之一
Vector
小结
Vector
是线程安全的List
,底层是数组实现的Vector
的每个方法都进行了加锁,数据操作效率低下Vector
每次扩容的大小都是原来数组大小的2
倍Vector
实现了RandomAccess
接口,支持随机读取,因此更加推荐使用for
循环进行遍历