首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 集合源碼分析(四):Vector<E> 線程安全的動態數組實現詳解

     編輯:Java 綜合教學

Java 集合源碼分析(四):Vector<E> 線程安全的動態數組實現詳解

類定義與繼承體系

public class Vector<E> 
    extends AbstractList<E> 
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  • 基於 Object[] 數組 實現,動態擴容。
  • JDK 1.0 早期類,方法級 synchronized 實現線程安全(相對安全,複合操作仍需外部同步)。
  • 實現 RandomAccess:支持快速隨機訪問(get/set O(1))。
  • 實現 Serializable、Cloneable。

核心字段

protected Object[] elementData; // 底層數組
protected int elementCount;     // 實際元素數量
protected int capacityIncrement; // 擴容增量系數 (構造器指定,0 表示翻倍)
private static final long serialVersionUID = -2767605614048989439L;

構造器體系

構造器行為
Vector()默認容量 10,增量 0 (翻倍擴容)
Vector(int initialCapacity)指定初始容量,增量 0
Vector(int initialCapacity, int capacityIncrement)指定初始容量與擴容增量
Vector(Collection<? extends E> c)包含集合元素,大小為集合尺寸

核心機制詳解

1. 擴容策略 ensureCapacityHelper

private void ensureCapacityHelper(int minCapacity) {
    int oldCapacity = elementData.length;
    if (minCapacity > oldCapacity) {
        Object[] oldData = elementData;
        // 關鍵邏輯:增量>0 則 +increment,否則 *2
        int newCapacity = (capacityIncrement > 0) 
            ? (oldCapacity + capacityIncrement) 
            : (oldCapacity * 2);
        if (newCapacity < minCapacity) newCapacity = minCapacity; // 保底
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
}

與 ArrayList 的「1.5 倍」不同,Vector 支持自定義增量,默認翻倍。

2. 線程安全:方法級 synchronized

幾乎所有公共方法(add、get、set、remove、indexOf、contains 等)均聲明 synchronized。

public synchronized E get(int index) { ... }
public synchronized boolean add(E e) { ... }
public synchronized E remove(int index) { ... }

注意:僅保證單個方法原子性。複合操作(如「檢查後添加」、「迭代中修改」)仍需外部同步,否則會有競態條件或 ConcurrentModificationException。

3. 空值處理

允許存儲 null 元素。查找方法(indexOf、lastIndexOf、contains)均分 o == null 和 o != null 兩條分支處理:

if (o == null) {
    for (int i = index; i < elementCount; i++)
        if (elementData[i] == null) return i;
} else {
    for (int i = index; i < elementCount; i++)
        if (o.equals(elementData[i])) return i;
}

4. 迭代器與 Fail-Fast

Vector 的 iterator()/listIterator() 返回的迭代器不支持 fail-fast(因方法同步,modCount 在同步塊外讀取)。但官方文檔建議同步迭代塊。

主要方法速覽

方法說明同步
addElement(E) / add(E)尾部添加synchronized
insertElementAt(E, index) / add(index, E)指定位置插入synchronized
removeElementAt(index) / remove(index)刪除指定位置synchronized
removeElement(Object) / remove(Object)刪除首個匹配元素synchronized
setElementAt(E, index) / set(index, E)替換指定位置synchronized
elementAt(index) / get(index)獲取指定位置synchronized
firstElement() / lastElement()首/尾元素synchronized
capacity()底層數組長度synchronized
size()實際元素數synchronized
trimToSize()縮容至實際大小synchronized
elements()返回 Enumeration (舊式迭代器)同步內部類
toArray() / toArray(T[])轉數組synchronized
clone()淺拷貝 (數組拷貝)synchronized

總結與現狀

  1. 實現本質:同步版 ArrayList,擴容策略可配(增量/翻倍)。
  2. 性能代價:粗粒度同步導致高併發下吞吐極低,單線程下也有同步開銷。
  3. 替代方案:
    • 單線程:ArrayList(無同步,擴容 1.5 倍)。
    • 多線程:Collections.synchronizedList(new ArrayList())(同步包裝器,靈活控制同步範圍)、CopyOnWriteArrayList(讀多寫少、無鎖讀)、ConcurrentLinkedQueue(併發隊列)。
  4. 現狀:已被淘汰,僅保留為兼容舊代碼。新項目不推薦使用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved