在 Java提高篇(二一)—–ArrayList 、Java 提高篇(二二)—LinkedList ,詳細(xì)講解了 ArrayList、linkedList 的原理和實(shí)現(xiàn)過程,對于 List 接口這里還介紹一個(gè)它的實(shí)現(xiàn)類 Vector,Vector 類可以實(shí)現(xiàn)可增長的對象數(shù)組。
Vector 可以實(shí)現(xiàn)可增長的對象數(shù)組。與數(shù)組一樣,它包含可以使用整數(shù)索引進(jìn)行訪問的組件。不過,Vector 的大小是可以增加或者減小的,以便適應(yīng)創(chuàng)建 Vector 后進(jìn)行添加或者刪除操作。
Vector 實(shí)現(xiàn) List 接口,繼承 AbstractList 類,所以我們可以將其看做隊(duì)列,支持相關(guān)的添加、刪除、修改、遍歷等功能。
Vector 實(shí)現(xiàn) RandmoAccess 接口,即提供了隨機(jī)訪問功能,提供提供快速訪問功能。在 Vector 我們可以直接訪問元素。
Vector 實(shí)現(xiàn)了 Cloneable 接口,支持 clone() 方法,可以被克隆。
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Vector 提供了四個(gè)構(gòu)造函數(shù):
/**
* 構(gòu)造一個(gè)空向量,使其內(nèi)部數(shù)據(jù)數(shù)組的大小為 10,其標(biāo)準(zhǔn)容量增量為零。
*/
public Vector() {
this(10);
}
/**
* 構(gòu)造一個(gè)包含指定 collection 中的元素的向量,這些元素按其 collection 的迭代器返回元素的順序排列。
*/
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);
}
/**
* 使用指定的初始容量和等于零的容量增量構(gòu)造一個(gè)空向量。
*/
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
/**
* 使用指定的初始容量和容量增量構(gòu)造一個(gè)空的向量。
*/
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object [initialCapacity];
this.capacityIncrement = capacityIncrement;
}
在成員變量方面,Vector 提供了 elementData , elementCount, capacityIncrement 三個(gè)成員變量。其中
elementData :”O(jiān)bject[] 類型的數(shù)組”,它保存了 Vector 中的元素。按照 Vector 的設(shè)計(jì) elementData 為一個(gè)動態(tài)數(shù)組,可以隨著元素的增加而動態(tài)的增長,其具體的增加方式后面提到(ensureCapacity 方法)。如果在初始化 Vector 時(shí)沒有指定容器大小,則使用默認(rèn)大小為 10.
elementCount:Vector
對象中的有效組件數(shù)。
capacityIncrement:向量的大小大于其容量時(shí),容量自動增加的量。如果在創(chuàng)建 Vector 時(shí),指定了 capacityIncrement 的大?。粍t,每次當(dāng) Vector 中動態(tài)數(shù)組容量增加時(shí)>,增加的大小都是 capacityIncrement。如果容量的增量小于等于零,則每次需要增大容量時(shí),向量的容量將增大一倍。
同時(shí) Vector 是線程安全的!
對于源碼的解析,LZ 在這里只就增加(add)刪除(remove)兩個(gè)方法進(jìn)行講解。
add(E e):將指定元素添加到此向量的末尾。
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1); //確認(rèn)容器大小,如果操作容量則擴(kuò)容操作
elementData[elementCount++] = e; //將e元素添加至末尾
return true;
}
這個(gè)方法相對而言比較簡單,具體過程就是先確認(rèn)容器的大小,看是否需要進(jìn)行擴(kuò)容操作,然后將E元素添加到此向量的末尾。
private void ensureCapacityHelper(int minCapacity) {
//如果
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 進(jìn)行擴(kuò)容操作
* 如果此向量的當(dāng)前容量小于minCapacity,則通過將其內(nèi)部數(shù)組替換為一個(gè)較大的數(shù)組倆增加其容量。
* 新數(shù)據(jù)數(shù)組的大小姜維原來的大小 + capacityIncrement,
* 除非 capacityIncrement 的值小于等于零,在后一種情況下,新的容量將為原來容量的兩倍,不過,如果此大小仍然小于 minCapacity,則新容量將為 minCapacity。
*/
private void grow(int minCapacity) {
int oldCapacity = elementData.length; //當(dāng)前容器大小
/*
* 新容器大小
* 若容量增量系數(shù)(capacityIncrement) > 0,則將容器大小增加到capacityIncrement
* 否則將容量增加一倍
*/
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);
}
/**
* 判斷是否超出最大范圍
* MAX_ARRAY_SIZE:private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
*/
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
對于 Vector 整個(gè)的擴(kuò)容過程,就是根據(jù) capacityIncrement 確認(rèn)擴(kuò)容大小的,若 capacityIncrement <= 0 則擴(kuò)大一倍,否則擴(kuò)大至 capacityIncrement 。當(dāng)然這個(gè)容量的最大范圍為 Integer.MAX_VALUE即,2^32 – 1,所以 Vector 并不是可以無限擴(kuò)充的。
/**
* 從Vector容器中移除指定元素E
*/
public boolean remove(Object o) {
return removeElement(o);
}
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj); //計(jì)算obj在Vector容器中位置
if (i >= 0) {
removeElementAt(i); //移除
return true;
}
return false;
}
public synchronized void removeElementAt(int index) {
modCount++; //修改次數(shù)+1
if (index >= elementCount) { //刪除位置大于容器有效大小
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
else if (index < 0) { //位置小于 < 0
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
//從指定源數(shù)組中復(fù)制一個(gè)數(shù)組,復(fù)制從指定的位置開始,到目標(biāo)數(shù)組的指定位置結(jié)束。
//也就是數(shù)組元素從j位置往前移
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--; //容器中有效組件個(gè)數(shù) - 1
elementData[elementCount] = null; //將向量的末尾位置設(shè)置為null
}
因?yàn)?Vector 底層是使用數(shù)組實(shí)現(xiàn)的,所以它的操作都是對數(shù)組進(jìn)行操作,只不過其是可以隨著元素的增加而動態(tài)的改變?nèi)萘看笮?,其?shí)現(xiàn)方法是是使用 Arrays.copyOf 方法將舊數(shù)據(jù)拷貝到一個(gè)新的大容量數(shù)組中。 Vector 的整個(gè)內(nèi)部實(shí)現(xiàn)都比較簡單,這里就不在重述了。
Vector 支持 4 種遍歷方式。
因?yàn)?Vector 實(shí)現(xiàn)了 RandmoAccess 接口,可以通過下標(biāo)來進(jìn)行隨機(jī)訪問。
for(int i = 0 ; i < vec.size() ; i++){
value = vec.get(i);
}
Iterator it = vec.iterator();
while(it.hasNext()){
value = it.next();
//do something
}
for(Integer value:vec){
//do something
}
Vector vec = new Vector<>();
Enumeration enu = vec.elements();
while (enu.hasMoreElements()) {
value = (Integer)enu.nextElement();
}