按照國際慣例,還是先來看下類簡介,有助于從整體上對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 ? get(i)==null : 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 ? e==null : 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 <= index && (o==null ? get(i)==null : 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 >= index && (o==null ? get(i)==null : 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() - 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】