天天看點

Java集合類架構源碼分析 之 Vector源碼解析 【8】

按照國際慣例,還是先來看下類簡介,有助于從整體上對Vecotr有一個大緻的了解:

/**
 * Vector 實作了一個增長的數組對象,像數組一樣,通過索引可以通路元素元件。
 * 然而,和數組一旦建立後,長度就保持不變的特性來說,在 Vector 建立之後,可以通過add/remove實作數組長度的放縮。
 * The {@code Vector} class implements a growable array of
 * objects. Like an array, it contains components that can be
 * accessed using an integer index. However, the size of a
 * {@code Vector} can grow or shrink as needed to accommodate
 * adding and removing items after the {@code Vector} has been created.
 *
 * 每個vector都試圖通過維護 capacity{容量}和 capacityIncrement{容量增量}來優化存儲管理。capacity{容量}至少要和vector大小一樣大;
 * 它通常更大,因為當元件添加到vector時,vector的存儲以塊的形式增加,大小為capacityIncrement{容量增量}。
 * 應用程式可以在插入大量元件之前增加向量的容量,這減少了增量重新配置設定的次數。
 * <p>Each vector tries to optimize storage management by maintaining a
 * {@code capacity} and a {@code capacityIncrement}. The
 * {@code capacity} is always at least as large as the vector
 * size; it is usually larger because as components are added to the
 * vector, the vector's storage increases in chunks the size of
 * {@code capacityIncrement}. An application can increase the
 * capacity of a vector before inserting a large number of
 * components; this reduces the amount of incremental reallocation.
 *
 * 作為 List 接口的前身,Vector 從一開始就秉持疊代器 iterator 快速失敗的特性。
 * <p><a name="fail-fast">
 * The iterators returned by this class's {@link #iterator() iterator} and
 * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em></a>:
 * if the vector is structurally modified at any time after the iterator is
 * created, in any way except through the iterator's own
 * {@link ListIterator#remove() remove} or
 * {@link ListIterator#add(Object) add} methods, the iterator will throw a
 * {@link ConcurrentModificationException}.  Thus, in the face of
 * concurrent modification, the iterator fails quickly and cleanly, rather
 * than risking arbitrary, non-deterministic behavior at an undetermined
 * time in the future.  The {@link Enumeration Enumerations} returned by
 * the {@link #elements() elements} method are <em>not</em> fail-fast.
 *
 * 快速失敗的特性隻能用來調試代碼,不能依賴該特性,來保證代碼品質。
 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
 * as it is, generally speaking, impossible to make any hard guarantees in the
 * presence of unsynchronized concurrent modification.  Fail-fast iterators
 * throw {@code ConcurrentModificationException} on a best-effort basis.
 * Therefore, it would be wrong to write a program that depended on this
 * exception for its correctness:  <i>the fail-fast behavior of iterators
 * should be used only to detect bugs.</i>
 *
 * 從 v1.2 開始,這個類被List接口實作來覆寫替代,同為 接口 Java Collection 架構的成員之一,不像新的接口實作,Vector是線程安全的。
 * 如果不需要線程安全,建議使用ArrayList來替換Vector.
 * <p>As of the Java 2 platform v1.2, this class was retrofitted to
 * implement the {@link List} interface, making it a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html" target="_blank" rel="external nofollow" >
 * Java Collections Framework</a>.  Unlike the new collection
 * implementations, {@code Vector} is synchronized.  If a thread-safe
 * implementation is not needed, it is recommended to use {@link
 * ArrayList} in place of {@code Vector}.
 *
 * @author  Lee Boynton
 * @author  Jonathan Payne
 * @see Collection
 * @see LinkedList
 * @since   JDK1.0
 */
           

從類簡介中,可以看出,雖然Vector出道的早,但沒有自成一派,更沒有發展壯大,仍然被納入了後來者居上的List的接口,這就說明了投資有風險,創業需謹慎,誰都想享受第一個吃螃蟹所帶來的紅利,但是也要注意背後所醞釀的風險。市場先行者,一般會為旁窺者提供第一手的素材,哪有坑,哪有利,付出的是自己,但是别人卻是無本萬利,成本效益最高,利益最大化。

探索者,有風險,成則傳奇,敗則被遺忘,試問各位,現在,還有誰在用Vector呢?

用于嘗試的人,他們可能會失敗,但是對于這樣的人,我們要學會敬重,因為,他們雖有不足,但是卻從無到有,披荊斬棘的走出了一條路,為後來者指明了方向,為繼往開來的人最大化的規避了風險。

他們雖敗猶榮,雖早已不在江湖,但江湖永遠都會有他的傳說。

這樣的大哥,值得我們花點精力來詳細的進行研究和認識,來看下Vector的方法:

public synchronized boolean add(Object arg0){}
public void add(int arg0,Object arg1){}
public synchronized Object remove(int arg0){}
public boolean remove(Object arg0){}
public synchronized Object get(int arg0){}
public synchronized boolean equals(Object arg0){}
public synchronized String toString(){}
public synchronized int hashCode(){}
public synchronized Object clone(){}
public int indexOf(Object arg0){}
public synchronized int indexOf(Object arg0,int arg1){}
public void clear(){}
public synchronized boolean isEmpty(){}
public synchronized int lastIndexOf(Object arg0,int arg1){}
public synchronized int lastIndexOf(Object arg0){}
public boolean contains(Object arg0){}
public synchronized void replaceAll(UnaryOperator arg0){}
public Enumeration elements(){}
public synchronized int size(){}
public synchronized List subList(int arg0,int arg1){}
public synchronized Object[] toArray(){}
public synchronized Object[] toArray(Object[] arg0){}
public synchronized Iterator iterator(){}
public Spliterator spliterator(){}
public synchronized boolean addAll(int arg0,Collection arg1){}
public synchronized boolean addAll(Collection arg0){}
public synchronized void addElement(Object arg0){}
public synchronized Object elementAt(int arg0){}
public synchronized void forEach(Consumer arg0){}
public synchronized Object set(int arg0,Object arg1){}
public synchronized int capacity(){}
public synchronized void ensureCapacity(int arg0){}
public synchronized void trimToSize(){}
public synchronized void copyInto(Object[] arg0){}
public synchronized void setSize(int arg0){}
public synchronized Object firstElement(){}
public synchronized Object lastElement(){}
public synchronized void setElementAt(Object arg0,int arg1){}
public synchronized void removeElementAt(int arg0){}
public synchronized void insertElementAt(Object arg0,int arg1){}
public synchronized boolean removeElement(Object arg0){}
public synchronized void removeAllElements(){}
public synchronized boolean containsAll(Collection arg0){}
public synchronized boolean removeAll(Collection arg0){}
public synchronized boolean retainAll(Collection arg0){}
public synchronized ListIterator listIterator(){}
public synchronized ListIterator listIterator(int arg0){}
public synchronized boolean removeIf(Predicate arg0){}
public synchronized void sort(Comparator arg0){}
public final void wait(long arg0,int arg1) throws InterruptedException{}
public final native void wait(long arg0) throws InterruptedException{}
public final void wait() throws InterruptedException{}
public final native Class getClass(){}
public final native void notify(){}
public final native void notifyAll(){}
public Stream stream(){}
public Stream parallelStream(){}
           

看出來特點沒有,很明顯,方法上一水的帶了synchronized關鍵字來進行修飾,這也是Vector号稱線程安全的主要原因,當然,什麼事都是有利有弊,過猶不及。安全是安全了,但是每個方法,會進行同步操作,遇到那種高并發的場景,分分鐘讓人頭秃,是以,沒有最好的設計,隻有最符合業務場景的設計。這也是1.2之後List出現後,對Vector進行修訂的主要因素。

對的,你又說了,這明顯其中有沒被 synchronized 修飾的方法,比如 下面的幾個方法:

public void add(int arg0,Object arg1){}
public boolean remove(Object arg0){}
public int indexOf(Object arg0){}
public void clear(){}
public boolean contains(Object arg0){}
public Enumeration elements(){}
public Spliterator spliterator(){}
           

是,小夥子絕對是孫悟空轉世,火眼真睛,但是這些方法沒有被synchronized關鍵詞修飾,隻是表象,我們來逐個看下這些方法的真是面目:

add(int ,Object)方法,是的,就是這麼粗暴,直接調用了insertElementAt(element,int)方法,僅僅是反轉了一下參數順序而已。

/**
     * 在對應的位置插入元素,并且移動其他的元素到指定的位置
     * Inserts the specified element at the specified position in this Vector.
     * Shifts the element currently at that position (if any) and any
     * subsequent elements to the right (adds one to their indices).
     *
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index > size()})
     * @since 1.2
     */
    public void add(int index, E element) {
        insertElementAt(element, index);
    }
           

remove(Object obj):同樣,也隻是調用了removeElement(obj)方法,沒做其他什麼處理:

/**
     * Removes the first occurrence of the specified element in this Vector
     * If the Vector does not contain the element, it is unchanged.  More
     * formally, removes the element with the lowest index i such that
     * {@code (o==null ? get(i)==null : o.equals(get(i)))} (if such
     * an element exists).
     *
     * @param o element to be removed from this Vector, if present
     * @return true if the Vector contained the specified element
     * @since 1.2
     */
    public boolean remove(Object o) {
        return removeElement(o);
    }
           

index(obj):調用了兩個參數的重載方法,index(obj,0),從索引=0處,開始搜尋查詢指定的元素obj:

/**
     * Returns the index of the first occurrence of the specified element
     * in this vector, or -1 if this vector does not contain the element.
     * More formally, returns the lowest index {@code i} such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     *
     * @param o element to search for
     * @return the index of the first occurrence of the specified element in
     *         this vector, or -1 if this vector does not contain the element
     */
    public int indexOf(Object o) {
        return indexOf(o, 0);
    }
           

clear(),調用removeAllElements(),清除所有的元素:

/**
     * Removes all of the elements from this Vector.  The Vector will
     * be empty after this call returns (unless it throws an exception).
     *
     * @since 1.2
     */
    public void clear() {
        removeAllElements();
    }
           

contains(obj),判斷Vector中是否包含指定的元素:

/**
     * 通過index(o,0),判斷Vector中是否包含指定的元素,包含,則傳回true,不包含,傳回false
     * Returns {@code true} if this vector contains the specified element.
     * More formally, returns {@code true} if and only if this vector
     * contains at least one element {@code e} such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     *
     * @param o element whose presence in this vector is to be tested
     * @return {@code true} if this vector contains the specified element
     */
    public boolean contains(Object o) {
        return indexOf(o, 0) >= 0;
    }
           

elements(),傳回vector中所有的元素,和iterator()比較類似,對元素進行疊代傳回的時候,也是經過了synchronized的修飾:

/**
     * 傳回 vector 的枚舉疊代器,傳回的對象将生成vector中的所有項,第一個元素是vector中index=0的元素,之後index=1,以此類推。
     * Returns an enumeration of the components of this vector. The
     * returned {@code Enumeration} object will generate all items in
     * this vector. The first item generated is the item at index {@code 0},
     * then the item at index {@code 1}, and so on.
     *
     * @return  an enumeration of the components of this vector
     * @see     Iterator
     */
    public Enumeration<E> elements() {
        return new Enumeration<E>() {
            int count = 0;

            public boolean hasMoreElements() {
                return count < elementCount;
            }

            public E nextElement() {
                synchronized (Vector.this) {
                    if (count < elementCount) {
                        return elementData(count++);
                    }
                }
                throw new NoSuchElementException("Vector Enumeration");
            }
        };
    }
           

spliterator()方法:

/**
     * 在vector上建立一個後期綁定以及快速失敗的 Spliterator。
     * Creates a <em><a href="Spliterator.html#binding" target="_blank" rel="external nofollow" >late-binding</a></em>
     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
     * list.
     *
     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
     * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}.
     * Overriding implementations should document the reporting of additional
     * characteristic values.
     *
     * @return a {@code Spliterator} over the elements in this list
     * @since 1.8
     */
    @Override
    public Spliterator<E> spliterator() {
        return new VectorSpliterator<>(this, null, 0, -1, 0);
    }
           

在1.2之後,Vector被納入Java Collection Framework架構,實作了List接口,是以大部分方法都是和之前介紹的List中的方法相似,不再贅述。

經過比對,在Vector中,存在如下的方法,在List中不存在,我們來進行逐一介紹:

int lastIndexOf(Object arg0,int arg1){}
Object elementAt(int arg0){}
Enumeration elements(){}
void setSize(int arg0){}
int indexOf(Object arg0,int arg1){}
void copyInto(Object[] arg0){}
void addElement(Object arg0){}
void removeAllElements(){}
Object lastElement(){}
void removeElementAt(int arg0){}
Object firstElement(){}
void setElementAt(Object arg0,int arg1){}
void insertElementAt(Object arg0,int arg1){}
boolean removeElement(Object arg0){}
int capacity(){}
           

lastIndexOf(Object,index):該方法擴充了lastIndex(O)方法,可以在符合邊界的基礎上,在指定的搜尋index基礎上,向前找第一個符合要求的元素,然後進行傳回。

/**
     * 從指定的index開始倒序查找,傳回清單中指定元素的最後一次出現的索引。元素不存在,則傳回-1.
     * Returns the index of the last occurrence of the specified element in
     * this vector, searching backwards from {@code index}, or returns -1 if
     * the element is not found.
     * More formally, returns the highest index {@code i} such that
     * <tt>(i&nbsp;&lt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i))))</tt>,
     * or -1 if there is no such index.
     *
     * @param o element to search for
     * @param index index to start searching backwards from
     * @return the index of the last occurrence of the element at position
     *         less than or equal to {@code index} in this vector;
     *         -1 if the element is not found.
     * @throws IndexOutOfBoundsException if the specified index is greater
     *         than or equal to the current size of this vector
     */
    public synchronized int lastIndexOf(Object o, int index) {
        if (index >= elementCount)
            throw new IndexOutOfBoundsException(index + " >= "+ elementCount);

        if (o == null) {
            for (int i = index; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
           

elementAt(int arg0),傳回指定索引上的元素:

/**
     * 和 get()相同,傳回指定索引位置的元素,和get()不同之處在于,抛出的異常資訊中,帶了list最大的邊界值
     * Returns the component at the specified index.
     *
     * <p>This method is identical in functionality to the {@link #get(int)}
     * method (which is part of the {@link List} interface).
     *
     * @param      index   an index into this vector
     * @return     the component at the specified index
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index >= size()})
     */
    public synchronized E elementAt(int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
        }

        return elementData(index);
    }
           

elements(),傳回vector上的所有元素的枚舉疊代器,在上邊已經介紹過,為進行統一,此處再次進行介紹:

/**
     * 枚舉疊代器
     * Returns an enumeration of the components of this vector. The
     * returned {@code Enumeration} object will generate all items in
     * this vector. The first item generated is the item at index {@code 0},
     * then the item at index {@code 1}, and so on.
     *
     * @return  an enumeration of the components of this vector
     * @see     Iterator
     */
    public Enumeration<E> elements() {
        return new Enumeration<E>() {
            int count = 0;

            public boolean hasMoreElements() {
                return count < elementCount;
            }

            public E nextElement() {
                synchronized (Vector.this) {
                    if (count < elementCount) {
                        return elementData(count++);
                    }
                }
                throw new NoSuchElementException("Vector Enumeration");
            }
        };
    }
           

setSize(),故名思意,設定vector的size(),這是一個很神奇的方法,如果指定的長度大于vector原來的容量,則進行擴容,否則,将指定索引(包括)之後的所有元素,都設定為null:

/**
     * 設定vector的長度,如果指定的size大于目前的長度,則進行擴容,否則,将指定索引及以後的所有元素,設定為null。
     * Sets the size of this vector. If the new size is greater than the
     * current size, new {@code null} items are added to the end of
     * the vector. If the new size is less than the current size, all
     * components at index {@code newSize} and greater are discarded.
     *
     * @param  newSize   the new size of this vector
     * @throws ArrayIndexOutOfBoundsException if the new size is negative
     */
    public synchronized void setSize(int newSize) {
        modCount++;
        if (newSize > elementCount) {
            ensureCapacityHelper(newSize);
        } else {
            for (int i = newSize ; i < elementCount ; i++) {
                elementData[i] = null;
            }
        }
        elementCount = newSize;
    }
           

indexOf(Object arg0,int arg1),和indexOf(Object)類似,傳回元素第一次出現的索引位置,但是在此基礎上做了擴充,可以指定搜尋的起始位置,在此起始位置之後,第一次出現的元素的索引,更加的靈活:

/**
     * 和 lastIndexOf()對應,傳回指定index之後,出現的第一個元素和指定元素相同的索引值。
     * Returns the index of the first occurrence of the specified element in
     * this vector, searching forwards from {@code index}, or returns -1 if
     * the element is not found.
     * More formally, returns the lowest index {@code i} such that
     * <tt>(i&nbsp;&gt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i))))</tt>,
     * or -1 if there is no such index.
     *
     * @param o element to search for
     * @param index index to start searching from
     * @return the index of the first occurrence of the element in
     *         this vector at position {@code index} or later in the vector;
     *         {@code -1} if the element is not found.
     * @throws IndexOutOfBoundsException if the specified index is negative
     * @see     Object#equals(Object)
     */
    public synchronized int indexOf(Object o, int index) {
        if (o == null) {
            for (int i = index ; i < elementCount ; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index ; i < elementCount ; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
           

copyInto(Object[] arg0),方法起一個好的名字,會節省更多的注釋,從方法名上可以看到,該方法就是将目前vector對應的底層數組,複制到指定的數組中,當然,長度需要等于目前數組的長度:

其實就是 System.arraycopy()指定參數的固定用法。

/**
     * 将目前 Vector 底層對應的數組,複制到指定的 anArray中。
	 * 如果指定的數組長度不夠,則會抛出 IndexOutOfBoundsException 異常。
	 * 如果插入的元素類型,和指定的數組的存儲類型不相符,則抛出 ArrayStoreException 異常。
     * Copies the components of this vector into the specified array.
     * The item at index {@code k} in this vector is copied into
     * component {@code k} of {@code anArray}.
     *
     * @param  anArray the array into which the components get copied
     * @throws NullPointerException if the given array is null
     * @throws IndexOutOfBoundsException if the specified array is not
     *         large enough to hold all the components of this vector
     * @throws ArrayStoreException if a component of this vector is not of
     *         a runtime type that can be stored in the specified array
     * @see #toArray(Object[])
     */
    public synchronized void copyInto(Object[] anArray) {
        System.arraycopy(elementData, 0, anArray, 0, elementCount);
    }
           

addElement(Object arg0),添加指定的元素到Vector的末尾,功能上和add()方法相同:

/**
     * 将指定的元素,添加到目前list的末尾。
     * Adds the specified component to the end of this vector,
     * increasing its size by one. The capacity of this vector is
     * increased if its size becomes greater than its capacity.
     *
     * <p>This method is identical in functionality to the
     * {@link #add(Object) add(E)}
     * method (which is part of the {@link List} interface).
     *
     * @param   obj   the component to be added
     */
    public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }
           

removeAllElements():删除所有的元素,功能上和clear()相同:

/**
     * 溢出所有的元素,并将長度設定為0.和 List 接口下的 clear()相同
     * Removes all components from this vector and sets its size to zero.
     *
     * <p>This method is identical in functionality to the {@link #clear}
     * method (which is part of the {@link List} interface).
     */
    public synchronized void removeAllElements() {
        modCount++;
        // Let gc do its work
        for (int i = 0; i < elementCount; i++)
            elementData[i] = null;

        elementCount = 0;
    }
           

 lastElement(),傳回最後一個元素:

/**
     * 傳回 Vector 的最後一個元素。index = size-1; Vector 為空,則抛出異常。
     * Returns the last component of the vector.
     *
     * @return  the last component of the vector, i.e., the component at index
     *          <code>size()&nbsp;-&nbsp;1</code>.
     * @throws NoSuchElementException if this vector is empty
     */
    public synchronized E lastElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(elementCount - 1);
    }
           

removeElementAt(int arg0),删除指定位置的元素:

/** 删除指定索引位置的元素,删除之後,在 Vector 中的比指定索引大或者相等的元素索引,都移動到比原來小的位置,vector的長度-1
     * Deletes the component at the specified index. Each component in
     * this vector with an index greater or equal to the specified
     * {@code index} is shifted downward to have an index one
     * smaller than the value it had previously. The size of this vector
     * is decreased by {@code 1}.
     *
     * <p>The index must be a value greater than or equal to {@code 0}
     * and less than the current size of the vector.
     *
     * removeElementAt(index)方法在功能上和List接口的remove()相同,但是remove()會傳回原來存儲的舊值。
     * <p>This method is identical in functionality to the {@link #remove(int)}
     * method (which is part of the {@link List} interface).  Note that the
     * {@code remove} method returns the old value that was stored at the
     * specified position.
     *
     * @param      index   the index of the object to remove
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index >= size()})
     */
    public synchronized void removeElementAt(int index) {
        modCount++;
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        else if (index < 0) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        int j = elementCount - index - 1;
        if (j > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        elementCount--;
        elementData[elementCount] = null; /* to let gc do its work */
    }
           

firstElement(),傳回第一個元素,如果Vector為空,則抛出異常:

/**
     * 傳回第一個元素内容 index = 0 ;Vector 為空,則抛出異常。
     * Returns the first component (the item at index {@code 0}) of
     * this vector.
     *
     * @return     the first component of this vector
     * @throws NoSuchElementException if this vector has no components
     */
    public synchronized E firstElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(0);
    }
           

setElementAt(Object arg0,int arg1):在指定索引位置,設定元素:

/**
     * 給指定的index索引位置設值,該位置目前值會被丢棄。
     * Sets the component at the specified {@code index} of this
     * vector to be the specified object. The previous component at that
     * position is discarded.
     *
     * <p>The index must be a value greater than or equal to {@code 0}
     * and less than the current size of the vector.
     *
     * 該方法功能上和List接口的set(int ,Object) set(int,E)相同。注意set(int,Object)颠倒了參數的順序,更比對數組的用法。同時也要注意set()方法傳回了舊值。
     * <p>This method is identical in functionality to the
     * {@link #set(int, Object) set(int, E)}
     * method (which is part of the {@link List} interface). Note that the
     * {@code set} method reverses the order of the parameters, to more closely
     * match array usage.  Note also that the {@code set} method returns the
     * old value that was stored at the specified position.
     *
     * @param      obj     what the component is to be set to
     * @param      index   the specified index
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index >= size()})
     */
    public synchronized void setElementAt(E obj, int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        elementData[index] = obj;
    }
           

insertElementAt(Object arg0,int arg1) 向指定索引位置插入元素,其他位置的元素發生移動。

/**
     * insertElementAt() == add();add()直接調用了 insertElementAt();
     * Inserts the specified object as a component in this vector at the
     * specified {@code index}. Each component in this vector with
     * an index greater or equal to the specified {@code index} is
     * shifted upward to have an index one greater than the value it had
     * previously.
     *
     * <p>The index must be a value greater than or equal to {@code 0}
     * and less than or equal to the current size of the vector. (If the
     * index is equal to the current size of the vector, the new element
     * is appended to the Vector.)
     *
     * <p>This method is identical in functionality to the
     * {@link #add(int, Object) add(int, E)}
     * method (which is part of the {@link List} interface).  Note that the
     * {@code add} method reverses the order of the parameters, to more closely
     * match array usage.
     *
     * @param      obj     the component to insert
     * @param      index   where to insert the new component
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index > size()})
     */
    public synchronized void insertElementAt(E obj, int index) {
        modCount++;
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        }
        ensureCapacityHelper(elementCount + 1); //首先擴充數組的容量+1
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);// 将指定索引及之後的元素,複制到原來索引+1的位置
        elementData[index] = obj;//将新的元素插入到指定的位置
        elementCount++;
    }
           

removeElement(Object arg0),删除元素:

/**
     * 删除在Vector中第一次出現的索引元素(即最小索引),如果元素在Vector中存在,原來大于指定索引的元素索引,-1.
     * Removes the first (lowest-indexed) occurrence of the argument
     * from this vector. If the object is found in this vector, each
     * component in the vector with an index greater or equal to the
     * object's index is shifted downward to have an index one smaller
     * than the value it had previously.
     *
     * <p>This method is identical in functionality to the
     * {@link #remove(Object)} method (which is part of the
     * {@link List} interface).
     *
     * @param   obj   the component to be removed
     * @return  {@code true} if the argument was a component of this
     *          vector; {@code false} otherwise.
     */
    public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }
           

capacity(),傳回Vector的容量:

/**
     * 傳回Vector的容量,和size()不同的是,size()傳回的是Vector中的元素數量,capacity()傳回的是目前不擴容前提下,可容納的元素數量
     * Returns the current capacity of this vector.
     *
     * @return  the current capacity (the length of its internal
     *          data array, kept in the field {@code elementData}
     *          of this vector)
     */
    public synchronized int capacity() {
        return elementData.length;
    }


	//樣例代碼:
		Vector<String> vector = new Vector<String>() ;
		vector.ensureCapacity(200);
		vector.add("abc");
		System.out.println(vector.capacity());
		System.out.println(vector.size());
	//	列印出:
	//	200
	//	1
           

可以看下示例代碼中,對vector容量設定的方法,ensureCapacity(200),設定Vector的大小,方法實作如下:

/**
     * 擴充 vector容量,確定清單可以至少容納參數指定的特定元素清單中的所有元素。
     * Increases the capacity of this vector, if necessary, to ensure
     * that it can hold at least the number of components specified by
     * the minimum capacity argument.
     *
     * 如果目前容量小于指定的 minCapacity,那麼容量會被擴充為較大的一個,通過重置被屬性 elementData 所持有的内部數組。
     * 新數組的長度,将會是原有容量+capacityIncrement,除非 capacityIncrement小于0,這種情況下容量将被擴充為原有容量的兩倍。
     * 如果擴充完之後,新數組的長度依然小于所需的 minCapacity,那麼新的容量就會被設定為 minCapacity。
     * <p>If the current capacity of this vector is less than
     * {@code minCapacity}, then its capacity is increased by replacing its
     * internal data array, kept in the field {@code elementData}, with a
     * larger one.  The size of the new data array will be the old size plus
     * {@code capacityIncrement}, unless the value of
     * {@code capacityIncrement} is less than or equal to zero, in which case
     * the new capacity will be twice the old capacity; but if this new size
     * is still smaller than {@code minCapacity}, then the new capacity will
     * be {@code minCapacity}.
     *
     * @param minCapacity the desired minimum capacity
     */
    public synchronized void ensureCapacity(int minCapacity) {
        if (minCapacity > 0) {
            modCount++;
            ensureCapacityHelper(minCapacity);
        }
    }
	
    /**
     * 我們可以看到,這個方法是非同步方法,為什麼可以這樣呢,是因為他的調用方 ensureCapacity()是同步方法,該方法作為私有方法被内部調用,無需再額外增加同步浪費資源。
     * This implements the unsynchronized semantics of ensureCapacity.
     * Synchronized methods in this class can internally call this
     * method for ensuring capacity without incurring the cost of an
     * extra synchronization.
     *
     * @see #ensureCapacity(int)
     */
    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;
		
		// 如果 capacityIncrement>0,那麼新的容量就是原有容量 oldCapacity+capacityIncrement,否則容量會變成 oldCapacity+oldCapacity,即變成原有容量的兩倍。
        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);
    }
           

在其中,可以看到兩點,值得我們注意:

1、在 ensureCapacity()方法實作中,有一個modCount++;

這個字段有什麼作用呢,其實還是從名字,可以看出來部分端倪,mod應該為modify的縮寫,取修改之意,Count++,就是自增,合起來就是修改次數的累加之和。具體有什麼用呢,來看該字段的注釋:

/**
     * 記錄了目前list結構修改的次數
     * The number of times this list has been <i>structurally modified</i>.
     * Structural modifications are those that change the size of the
     * list, or otherwise perturb it in such a fashion that iterations in
     * progress may yield incorrect results.
     *
     * 如果疊代器在疊代期間,該值發生了意外改變,即有其他并發線程在修改目前list,那麼就會抛出 ConcurrentModificationException 異常。
     * <p>This field is used by the iterator and list iterator implementation
     * returned by the {@code iterator} and {@code listIterator} methods.
     * If the value of this field changes unexpectedly, the iterator (or list
     * iterator) will throw a {@code ConcurrentModificationException} in
     * response to the {@code next}, {@code remove}, {@code previous},
     * {@code set} or {@code add} operations.  This provides
     * <i>fail-fast</i> behavior, rather than non-deterministic behavior in
     * the face of concurrent modification during iteration.
     *
     * 子類是否使用該字段是可選的,如果子類希望提供一個快速失敗的疊代器(以及清單疊代器),
	 * 隻需要在add/remove(以及其他可能對清單結構發生改變的方法中)對該字段進行加操作。
	 * 對于add/remove的一次調用,對于該字段的增加不能超過1.否則清單會抛出僞裝的 ConcurrentModificationExceptions 異常。
	 * 如果子類實作不希望提供快速失敗疊代器,可以忽略這個字段。
     * <p><b>Use of this field by subclasses is optional.</b> If a subclass
     * wishes to provide fail-fast iterators (and list iterators), then it
     * merely has to increment this field in its {@code add(int, E)} and
     * {@code remove(int)} methods (and any other methods that it overrides
     * that result in structural modifications to the list).  A single call to
     * {@code add(int, E)} or {@code remove(int)} must add no more than
     * one to this field, or the iterators (and list iterators) will throw
     * bogus {@code ConcurrentModificationExceptions}.  If an implementation
     * does not wish to provide fail-fast iterators, this field may be
     * ignored.
     */
    protected transient int modCount = 0;
           

可以看到,主要是為了統計一些改變資料結構的方法,諸如add/remove/等等,這些方法的調用次數,用來在建立疊代器之後,進行周遊的整個聲明周期中,作為目前結構是否發生意外修改的一個依據,如果發現目前list的長度和預期的不符,表明已經發生了修改,那麼就會抛出 ConcurrentModificationException 異常。來看具體的實作源碼:

首先看建立疊代器的源碼,iterator():

public synchronized Iterator<E> iterator() {
        return new Itr();
    }
           

方法傳回了一個Itr内部類的執行個體,再來看該類源碼:

private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        public boolean hasNext() {
            // Racy but within spec, since modifications are checked
            // within or after synchronization in next/previous
            return cursor != elementCount;
        }

        public E next() {
            synchronized (Vector.this) {
                checkForComodification(); // 同步周遊該 Vector過程中,會對該Vector進行檢查
                int i = cursor;
                if (i >= elementCount)
                    throw new NoSuchElementException();
                cursor = i + 1;
                return elementData(lastRet = i);
            }
        }

        public void remove() {
            if (lastRet == -1)
                throw new IllegalStateException();
            synchronized (Vector.this) {
                checkForComodification();
                Vector.this.remove(lastRet);
                expectedModCount = modCount;
            }
            cursor = lastRet;
            lastRet = -1;
        }

        @Override
        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            synchronized (Vector.this) {
                final int size = elementCount;
                int i = cursor;
                if (i >= size) {
                    return;
                }
        @SuppressWarnings("unchecked")
                final E[] elementData = (E[]) Vector.this.elementData;
                if (i >= elementData.length) {
                    throw new ConcurrentModificationException();
                }
                while (i != size && modCount == expectedModCount) {
                    action.accept(elementData[i++]);
                }
                // update once at end of iteration to reduce heap write traffic
                cursor = i;
                lastRet = i - 1;
                checkForComodification();
            }
        }

        final void checkForComodification() {
			// 檢查主要邏輯,就是判斷目前的值(可以外部修改)和預期的值(在建立iterator時已經被固定初始化)是否相同,
			// 如果不同,那就代表除了目前iterator之外,有其他的操作對該list進行修改,就會抛出 ConcurrentModificationException 異常。
            if (modCount != expectedModCount) 
                throw new ConcurrentModificationException();
        }
    }
           

 從 上述内部類中 checkForComodification()方法的實作,我們也了解了流傳江湖已久的 ConcurrentModificationException 的發生機理。

2、ensureCapacity()方法中,調用了ensureCapacityHelper()方法,該方法為非同步方法。

那麼問題可能來了,就是作為以線程安全著稱的Vector,對Vector進行擴容這麼重要的操作,怎麼沒有 synchronized 關鍵字修飾呢?

其實原因在上述ensureCapacity()源碼解析中,已經有了說明,為了進一步說明和加深記憶,在此處再重複說明一次。

原因其實很簡單,就是雖然 ensureCapacityHelper()不是線程安全的,但是它是内部私有方法,外部能獨立調用,在類内部實作中,我們可以看到,它的調用方ensureCapacity()是線程安全的,是以無需再額外的增加線程安全控制的開銷。

對于List接口下,還有一篇Stack的介紹,就可以結束了,該接口下,其他主要類源碼的分析有這些:

其他相關文章:

Java集合類架構源碼分析 之 Stack源碼解析 【9】

Java集合類架構源碼分析 之 Vector源碼解析 【8】

Java集合類架構源碼分析 之 AttributeList源碼解析 【7】

Java集合類架構源碼分析 之 RoleList源碼解析 【6】

Java集合類架構源碼分析 之 CopyOnWriteArrayList源碼解析 【5】

Java集合類架構源碼分析 之 LinkedList源碼解析 【4】

Java集合類架構源碼分析 之 ArrayList源碼解析 【3】

Java集合類架構源碼分析 之 接口中是否可以有方法實作 【2】

Java集合類架構源碼分析 之 List 接口源碼分析 【1】