java.util.Vector 是 JDK 1.0 時代的同步動態數組,雖已被 ArrayList + 併發包取代,但在大量遺留系統、教學代碼中仍廣泛存在。本文從源碼級剖析其同步機制、擴容策略、Enumeration 遍歷特性,並給出遍歷效率實測數據。
public class Vector<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable { }
AbstractList,實現 List、RandomAccess(支持快速隨機訪問)、Cloneable、Serializable。synchronized → 線程安全,但鎖粒度粗、爭用時性能瓶頸明顯。protected Object[] elementData + int elementCount 實現動態數組。Enumeration 遍歷(遺留特性),現代代碼建議用 Iterator/for-each。| 構造函數 | 說明 |
|---|---|
Vector() | 默認容量 10,擴容翻倍 |
Vector(int initialCapacity) | 指定初始容量,擴容翻倍 |
Vector(int initialCapacity, int capacityIncrement) | 指定初始容量與固定增量(>0 時每次擴容 +increment) |
Vector(Collection<? extends E> c) | 複製構造,容量 = 集合大小 |
ensureCapacityHelperprivate void ensureCapacityHelper(int minCapacity) {
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object[] oldData = elementData;
int newCapacity = (capacityIncrement > 0)
? (oldCapacity + capacityIncrement) // 固定增量模式
: (oldCapacity * 2); // 默認翻倍模式
if (newCapacity < minCapacity) newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
對比 ArrayList:ArrayList 固定 1.5 倍 + 1((old*3)/2+1),Vector 可配置固定增量或翻倍,靈活但擴容頻率可能更高。
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
public synchronized E get(int index) {
if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index);
return (E) elementData[index];
}
所有修改(add/remove/set/insert)與讀取(get/size/isEmpty)均同步 → 甚至單線程下也承擔鎖開銷。
// insertElementAt(index, obj)
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
elementData[index] = obj;
elementCount++;
// removeElementAt(index)
int j = elementCount - index - 1;
if (j > 0) System.arraycopy(elementData, index + 1, elementData, index, j);
elementCount--;
elementData[elementCount] = null; // 釋放引用助 GC
public Enumeration<E> elements() {
return new Enumeration<E>() {
int count = 0;
public boolean hasMoreElements() { return count < elementCount; }
public E nextElement() {
synchronized (Vector.this) { // 雙重同步
if (count < elementCount) return (E) elementData[count++];
}
throw new NoSuchElementException("Vector Enumeration");
}
};
}
// 測試代碼片段
iteratorThroughRandomAccess:6 ms // for (int i=0; i
結論:實現RandomAccess的 Vector,下標隨機訪問最快,Enumerator 次之,迭代器最慢。實際開發首選for (int i=0; i。
| 維度 | Vector | ArrayList |
|---|---|---|
| 線程安全 | 方法級 synchronized | 非線程安全 |
| 序列化 | 未實現 Serializable | 實現 Serializable |
| 擴容策略 | 可配增量 或 2倍 | 固定 1.5倍+1 |
| 構造函數 | 4 個 | 3 個 |
| Enumeration | 支持 | 不支持 |
| 性能(單線程) | 較低(鎖開銷) | 極高 |
import java.util.*;
public class VectorDemo {
public static void main(String[] args) {
Vector<String> vec = new Vector<>();
vec.add("1"); vec.add("2"); vec.add("3"); vec.add("4"); vec.add("5");
// 修改與插入
vec.set(0, "100");
vec.add(2, "300"); // 索引 2 插入
System.out.println("vec: " + vec); // [100, 2, 300, 3, 4, 5]
// 查找
System.out.println("indexOf(100): " + vec.indexOf("100")); // 0
System.out.println("lastIndexOf(100): " + vec.lastIndexOf("100")); // 0
// 首尾元素
System.out.println("first: " + vec.firstElement()); // 100
System.out.println("last: " + vec.lastElement()); // 5
System.out.println("elementAt(2): " + vec.elementAt(2)); // 300
// 容量與大小
System.out.println("size: " + vec.size() + ", capacity: " + vec.capacity());
// 子列表
System.out.println("subList(1,4): " + vec.subList(1, 4)); // [2, 300, 3]
// Enumeration 遍歷
System.out.println("\nEnumeration 遍歷:");
for (Enumeration<String> enu = vec.elements(); enu.hasMoreElements(); )
System.out.println(enu.nextElement());
// retainAll 保留交集
Vector<String> retain = new Vector<>();
retain.add("100"); retain.add("300");
vec.retainAll(retain);
System.out.println("\nretainAll 後: " + vec); // [100, 300]
// 轉數組
String[] arr = vec.toArray(new String[0]);
for (String s : arr) System.out.println("arr: " + s);
// 清空
vec.clear();
System.out.println("isEmpty: " + vec.isEmpty());
}
}
ArrayList(性能最優)。CopyOnWriteArrayList(寫時復制,遍歷無鎖)。Collections.synchronizedList(new ArrayList()) 或 手動加鎖 ArrayList。ConcurrentLinkedQueue、ArrayBlockingQueue、ConcurrentLinkedDeque。