概述
上文「JDK源碼分析-ArrayList」主要分析了 ArrayList 的實現(xiàn)原理。本文分析 List 接口的另一個實現(xiàn)類:Vector。
Vector 的內(nèi)部實現(xiàn)與 ArrayList 類似,也可以理解為一個「可變數(shù)組」。其繼承結構如下(省略部分接口):
PS: 由于 Vector 目前使用較少,且官方也推薦在無線程安全的需求時使用 ArrayList 代替 Vector,這里僅研究其實現(xiàn)原理。
stackoverflow 也有相關的討論:
https://stackoverflow.com/questions/1386275/why-is-JAVA-vector-and-stack-class-considered-obsolete-or-deprecated
仍然從其構造器入手進行分析。
構造器
Vector 對外提供四個構造器(內(nèi)部可以認為是兩個),其一:
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 內(nèi)部也維護了一個 Object 類型的數(shù)組(elementData)來存儲元素(默認初始容量也是 10)。不同的是:Vector 比 ArrayList 的構造器多了一個參數(shù) capacityIncrement,該變量也導致了二者的擴容方式略有不同,后面進行分析。
其二:入?yún)榧系臉嬙炱?/p>
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); }
擴容原理分析
我們?nèi)詮钠?add() 方法入手進行分析:
public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }
注意這里的關鍵字 synchronized。觀察可以發(fā)現(xiàn):Vector 內(nèi)部許多方法都使用了該關鍵字,這也是 Vector 實現(xiàn)線程安全的方式,簡單粗暴!
其擴容方法實現(xiàn)如下:
/** * 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 內(nèi)部調用該方法的地方都使用了 synchronized 關鍵字進行同步,這里不再額外使用 */ private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code // 大于數(shù)組容量時再進行擴容操作 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 的擴容方式基本一致,只是新容量的計算方式有所不同,這里分析下其新容量大?。?/p>
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
Vector 計算擴容后的新容量時,根據(jù) capacityIncrement 的值可以分為兩種情況:
1. capacityIncrement > 0:新容量 = 舊容量 + capacityIncrement;
2. capacityIncrement <= 0:新容量 = 舊容量 * 2。
線程安全性
Vector 是線程安全的,它實現(xiàn)線程安全的方式也很簡單粗暴:直接在方法上使用 synchronized 關鍵字進行同步。
Vector 小結
1. 與 ArrayList 類似,Vector 也可以認為是「可變數(shù)組」;
2. 擴容原理與 ArrayList 基本一致,只是新容量計算方式略有不同:指定增長容量時,新容量為舊容量 + 增長容量;否則擴容為舊容量的 2 倍;
3. 線程安全的,實現(xiàn)方式簡單(synchronized);
4. 當前使用較少,這里僅學習其實現(xiàn)原理。
Stay hungry, stay foolish.