1. 程式人生 > 程式設計 >JDK原始碼分析-Vector

JDK原始碼分析-Vector

概述


上文「JDK原始碼分析-ArrayList」主要分析了 ArrayList 的實現原理。本文分析 List 介面的另一個實現類:Vector。

Vector 的內部實現與 ArrayList 類似,也可以理解為一個「可變陣列」。其繼承結構如下(省略部分介面):


PS: 由於 Vector 目前使用較少,且官方也推薦在無執行緒安全的需求時使用 ArrayList 代替 Vector,這裡僅研究其實現原理。


stackoverflow 也有相關的討論:

https://stackoverflow.com/questions/1386275/why-is-java-vector-and-stack-class-considered-obsolete-or-deprecated

仍然從其構造器入手進行分析。


構造器

Vector 對外提供四個構造器(內部可以認為是兩個),其一:

protected Object[] elementData;

protected int capacityIncrement;

// 無參構造器
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;
}        

與 ArrayList 類似,Vector 內部也維護了一個 Object 型別的陣列(elementData)來儲存元素(預設初始容量也是 10)。不同的是:Vector 比 ArrayList 的構造器多了一個引數 capacityIncrement,該變數也導致了二者的擴容方式略有不同,後面進行分析。

其二:入參為集合的構造器

public Vector(Collection<? extends E> c) {
    elementData = c.toArray();
    elementCount = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}       

擴容原理分析

我們仍從其 add() 方法入手進行分析:

public synchronized boolean add(E e) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = e;
    return true;
}    

注意這裡的關鍵字 synchronized。觀察可以發現:Vector 內部許多方法都使用了該關鍵字,這也是 Vector 實現執行緒安全的方式,簡單粗暴!

其擴容方法實現如下:

/**
 * The number of valid components in this {@code Vector} object.
 * Components elementData[0] through
 * elementData[elementCount-1] are the actual items.
 */

protected int elementCount;

/*
 * 該方法是非同步的
 * 因為 Vector 內部呼叫該方法的地方都使用了 synchronized 關鍵字進行同步,這裡不再額外使用
 */

private void ensureCapacityHelper(int minCapacity) {
    // overflow-conscious code
    // 大於陣列容量時再進行擴容操作
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) {
    // overflow-conscious code
    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;
}                

從這裡可以看出,Vector 與 ArrayList 的擴容方式基本一致,只是新容量的計算方式有所不同,這裡分析下其新容量大小:

int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);

Vector 計算擴容後的新容量時,根據 capacityIncrement 的值可以分為兩種情況:

1. capacityIncrement > 0:新容量 = 舊容量 + capacityIncrement;

2. capacityIncrement <= 0:新容量 = 舊容量 * 2。

執行緒安全性

Vector 是執行緒安全的,它實現執行緒安全的方式也很簡單粗暴:直接在方法上使用 synchronized 關鍵字進行同步。

Vector 小結

1. 與 ArrayList 類似,Vector 也可以認為是「可變陣列」;

2. 擴容原理與 ArrayList 基本一致,只是新容量計算方式略有不同:指定增長容量時,新容量為舊容量 + 增長容量;否則擴容為舊容量的 2 倍;

3. 執行緒安全的,實現方式簡單(synchronized);

4. 當前使用較少,這裡僅學習其實現原理。


Stay hungry,stay foolish.