java提高篇(二九)-----Vector


java提高篇(二一)—–ArrayListjava提高篇(二二)—LinkedList,詳細講解了ArrayList、linkedList的原理和實現過程,對於List接口這里還介紹一個它的實現類Vector,Vector 類可以實現可增長的對象數組。

一、Vector簡介

Vector可以實現可增長的對象數組。與數組一樣,它包含可以使用整數索引進行訪問的組件。不過,Vector的大小是可以增加或者減小的,以便適應創建Vector后進行添加或者刪除操作。

Vector實現List接口,繼承AbstractList類,所以我們可以將其看做隊列,支持相關的添加、刪除、修改、遍歷等功能。

Vector實現RandmoAccess接口,即提供了隨機訪問功能,提供提供快速訪問功能。在Vector我們可以直接訪問元素。

Vector 實現了Cloneable接口,支持clone()方法,可以被克隆。

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

Vector提供了四個構造函數:

/**
     * 構造一個空向量,使其內部數據數組的大小為 10,其標准容量增量為零。
     */
     public Vector() {
            this(10);
     }
</span><span style="color: #008000">/**</span><span style="color: #008000">
 * 構造一個包含指定 collection 中的元素的向量,這些元素按其 collection 的迭代器返回元素的順序排列。
 </span><span style="color: #008000">*/</span>
<span style="color: #0000ff">public</span> Vector(Collection&lt;? <span style="color: #0000ff">extends</span> E&gt;<span style="color: #000000"> c) {
    elementData </span>=<span style="color: #000000"> c.toArray();
    elementCount </span>=<span style="color: #000000"> elementData.length;
    </span><span style="color: #008000">//</span><span style="color: #008000"> c.toArray might (incorrectly) not return Object[] (see 6260652)</span>
    <span style="color: #0000ff">if</span> (elementData.getClass() != Object[].<span style="color: #0000ff">class</span><span style="color: #000000">)
        elementData </span>=<span style="color: #000000"> Arrays.copyOf(elementData, elementCount,
                Object[].</span><span style="color: #0000ff">class</span><span style="color: #000000">);
}

</span><span style="color: #008000">/**</span><span style="color: #008000">
 * 使用指定的初始容量和等於零的容量增量構造一個空向量。
 </span><span style="color: #008000">*/</span>
<span style="color: #0000ff">public</span> Vector(<span style="color: #0000ff">int</span><span style="color: #000000"> initialCapacity) {
    </span><span style="color: #0000ff">this</span>(initialCapacity, 0<span style="color: #000000">);
}

</span><span style="color: #008000">/**</span><span style="color: #008000">
 *  使用指定的初始容量和容量增量構造一個空的向量。
 </span><span style="color: #008000">*/</span>
<span style="color: #0000ff">public</span> Vector(<span style="color: #0000ff">int</span> initialCapacity, <span style="color: #0000ff">int</span><span style="color: #000000"> capacityIncrement) {
    </span><span style="color: #0000ff">super</span><span style="color: #000000">();
    </span><span style="color: #0000ff">if</span> (initialCapacity &lt; 0<span style="color: #000000">)
        </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> IllegalArgumentException(&quot;Illegal Capacity: &quot;+<span style="color: #000000">
                                           initialCapacity);
    </span><span style="color: #0000ff">this</span>.elementData = <span style="color: #0000ff">new</span><span style="color: #000000"> Object[initialCapacity];
    </span><span style="color: #0000ff">this</span>.capacityIncrement =<span style="color: #000000"> capacityIncrement;
}</span></pre>

在成員變量方面,Vector提供了elementData , elementCount, capacityIncrement三個成員變量。其中

elementData :"Object[]類型的數組",它保存了Vector中的元素。按照Vector的設計elementData為一個動態數組,可以隨着元素的增加而動態的增長,其具體的增加方式后面提到(ensureCapacity方法)。如果在初始化Vector時沒有指定容器大小,則使用默認大小為10.

elementCount:Vector 對象中的有效組件數。

capacityIncrement:向量的大小大於其容量時,容量自動增加的量。如果在創建Vector時,指定了capacityIncrement的大小;則,每次當Vector中動態數組容量增加時>,增加的大小都是capacityIncrement。如果容量的增量小於等於零,則每次需要增大容量時,向量的容量將增大一倍。

同時Vector是線程安全的!

二、源碼解析

對於源碼的解析,LZ在這里只就增加(add)刪除(remove)兩個方法進行講解。

2.1增加:add(E e)

add(E e):將指定元素添加到此向量的末尾。

public synchronized boolean add(E e) {
        modCount++;     
        ensureCapacityHelper(elementCount + 1);    //確認容器大小,如果操作容量則擴容操作
        elementData[elementCount++] = e;   //將e元素添加至末尾
        return true;
    }

這個方法相對而言比較簡單,具體過程就是先確認容器的大小,看是否需要進行擴容操作,然后將E元素添加到此向量的末尾。

private void ensureCapacityHelper(int minCapacity) {
        //如果
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
</span><span style="color: #008000">/**</span><span style="color: #008000">
 * 進行擴容操作
 * 如果此向量的當前容量小於minCapacity,則通過將其內部數組替換為一個較大的數組倆增加其容量。
 * 新數據數組的大小姜維原來的大小 + capacityIncrement,
 * 除非 capacityIncrement 的值小於等於零,在后一種情況下,新的容量將為原來容量的兩倍,不過,如果此大小仍然小於 minCapacity,則新容量將為 minCapacity。
 </span><span style="color: #008000">*/</span>
<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> grow(<span style="color: #0000ff">int</span><span style="color: #000000"> minCapacity) {
    </span><span style="color: #0000ff">int</span> oldCapacity = elementData.length;     <span style="color: #008000">//</span><span style="color: #008000">當前容器大小</span>
    <span style="color: #008000">/*</span><span style="color: #008000">
     * 新容器大小
     * 若容量增量系數(capacityIncrement) &gt; 0,則將容器大小增加到capacityIncrement
     * 否則將容量增加一倍
     </span><span style="color: #008000">*/</span>
    <span style="color: #0000ff">int</span> newCapacity = oldCapacity + ((capacityIncrement &gt; 0) ?<span style="color: #000000">
                                     capacityIncrement : oldCapacity);
    
    </span><span style="color: #0000ff">if</span> (newCapacity - minCapacity &lt; 0<span style="color: #000000">)
        newCapacity </span>=<span style="color: #000000"> minCapacity;
    
    </span><span style="color: #0000ff">if</span> (newCapacity - MAX_ARRAY_SIZE &gt; 0<span style="color: #000000">)
        newCapacity </span>=<span style="color: #000000"> hugeCapacity(minCapacity);
    
    elementData </span>=<span style="color: #000000"> Arrays.copyOf(elementData, newCapacity);
}

</span><span style="color: #008000">/**</span><span style="color: #008000">
 * 判斷是否超出最大范圍
 * MAX_ARRAY_SIZE:private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 </span><span style="color: #008000">*/</span>
<span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span> hugeCapacity(<span style="color: #0000ff">int</span><span style="color: #000000"> minCapacity) {
    </span><span style="color: #0000ff">if</span> (minCapacity &lt; 0<span style="color: #000000">)
        </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span><span style="color: #000000"> OutOfMemoryError();
    </span><span style="color: #0000ff">return</span> (minCapacity &gt; MAX_ARRAY_SIZE) ?<span style="color: #000000"> Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}</span></pre>

對於Vector整個的擴容過程,就是根據capacityIncrement確認擴容大小的,若capacityIncrement <= 0 則擴大一倍,否則擴大至capacityIncrement 。當然這個容量的最大范圍為Integer.MAX_VALUE即,2^32 - 1,所以Vector並不是可以無限擴充的。

2.2、remove(Object o)

/**
     * 從Vector容器中移除指定元素E
     */
    public boolean remove(Object o) {
        return removeElement(o);
    }
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">synchronized</span> <span style="color: #0000ff">boolean</span><span style="color: #000000"> removeElement(Object obj) {
    modCount</span>++<span style="color: #000000">;
    </span><span style="color: #0000ff">int</span> i = indexOf(obj);   <span style="color: #008000">//</span><span style="color: #008000">計算obj在Vector容器中位置</span>
    <span style="color: #0000ff">if</span> (i &gt;= 0<span style="color: #000000">) {
        removeElementAt(i);   </span><span style="color: #008000">//</span><span style="color: #008000">移除</span>
        <span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span><span style="color: #000000">;
    }
    </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span><span style="color: #000000">;
}

</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">synchronized</span> <span style="color: #0000ff">void</span> removeElementAt(<span style="color: #0000ff">int</span><span style="color: #000000"> index) {
    modCount</span>++;     <span style="color: #008000">//</span><span style="color: #008000">修改次數+1</span>
    <span style="color: #0000ff">if</span> (index &gt;= elementCount) {   <span style="color: #008000">//</span><span style="color: #008000">刪除位置大於容器有效大小</span>
        <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArrayIndexOutOfBoundsException(index + &quot; &gt;= &quot; +<span style="color: #000000"> elementCount);
    }
    </span><span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (index &lt; 0) {    <span style="color: #008000">//</span><span style="color: #008000">位置小於 &lt; 0</span>
        <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span><span style="color: #000000"> ArrayIndexOutOfBoundsException(index);
    }
    </span><span style="color: #0000ff">int</span> j = elementCount - index - 1<span style="color: #000000">;
    </span><span style="color: #0000ff">if</span> (j &gt; 0<span style="color: #000000">) {   
        </span><span style="color: #008000">//</span><span style="color: #008000">從指定源數組中復制一個數組,復制從指定的位置開始,到目標數組的指定位置結束。
        </span><span style="color: #008000">//</span><span style="color: #008000">也就是數組元素從j位置往前移</span>
        System.arraycopy(elementData, index + 1<span style="color: #000000">, elementData, index, j);
    }
    elementCount</span>--;   <span style="color: #008000">//</span><span style="color: #008000">容器中有效組件個數 - 1</span>
    elementData[elementCount] = <span style="color: #0000ff">null</span>;    <span style="color: #008000">//</span><span style="color: #008000">將向量的末尾位置設置為null</span>
}</pre>

因為Vector底層是使用數組實現的,所以它的操作都是對數組進行操作,只不過其是可以隨着元素的增加而動態的改變容量大小,其實現方法是是使用Arrays.copyOf方法將舊數據拷貝到一個新的大容量數組中。Vector的整個內部實現都比較簡單,這里就不在重述了。

三、Vector遍歷

Vector支持4種遍歷方式。

3.1、隨機訪問

因為Vector實現了RandmoAccess接口,可以通過下標來進行隨機訪問。

for(int i = 0 ; i < vec.size() ; i++){
        value = vec.get(i);
    }

3.2、迭代器

Iterator it = vec.iterator();
    while(it.hasNext()){
        value = it.next();
        //do something
    }

3.2、for循環

for(Integer value:vec){
        //do something
    }

3.4、Enumeration循環

Vector vec = new Vector<>();
    Enumeration enu = vec.elements();
    while (enu.hasMoreElements()) {
        value = (Integer)enu.nextElement();
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM