Vector 為 JDK 1.0 即存在的動態陣列,底層由 Object[] 實現,所有方法均以 synchronized 修飾,號稱「線程安全」。
Vector v1 = new Vector();
v1.addElement("one");
v1.addElement(new Integer(1));
v1.insertElement("three", 2); // 指定位置插入
v1.setElementAt("four", 2); // 指定位置替換
v1.removeElement(integer1); // 移除第一個匹配元素
Enumeration enum = v1.elements(); // 迭代遍歷
System.out.println(v1.indexOf(integer1)); // 正向查找索引
System.out.println(v1.lastIndexOf(integer1)); // 反向查找索引
v1.setSize(4); // 截斷/擴展大小
不同於 ArrayList 的 1.5 倍擴容,Vector 預設採用 1 倍擴容(即容量翻倍):
protected int capacityIncrement; // 可指定增量,預設 0 表示翻倍
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
// ... 邊界檢查與複製
}
若建構時指定 capacityIncrement,則按指定增量擴容;否則預設翻倍。
雖然所有公共方法皆加 synchronized,但在複合操作(如「判斷大小 → 獲取/移除」)下仍不安全:
// 多線程併發測試
private static Vector<Integer> vector = new Vector<>();
public static void main(String[] args) {
while (true) {
for (int i = 0; i < 10; i++) vector.add(i);
new Thread(() -> {
for (int i = 0; i < vector.size(); i++) vector.remove(i);
}).start();
new Thread(() -> {
for (int i = 0; i < vector.size(); i++) System.out.println(vector.get(i));
}).start();
// 短時間內拋出 ArrayIndexOutOfBoundsException
}
}
原因:size()、get()、remove() 雖各自同步,但組合操作非原子。線程 A 刪除索引 i 後,線程 B 仍嘗試訪問原索引 i,導致越界。
synchronized(vector) 包裹複合操作。Collections.synchronizedList(new ArrayList<>()) 並同步複合操作。CopyOnWriteArrayList 或並發佇列。Vector 的「線程安全」僅限單一方法層面,複合業務邏輯仍需外部同步。現代開發多傾向 ArrayList + 顯式同步或並發容器,Vector 已逐漸淡出主流。