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,該變數也導致了二者的擴容方式略有不同,後面進行分析。
其二:入參為集合的構造器
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() 方法入手進行分析:
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 的擴容方式基本一致,只是新容量的計算方式有所不同,這裡分析下其新容量大小:
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.