一、概述
我們都知道,在Java的Collections包含了List和Set,而List里面有ArrayList、LinkedList、還有Vector,對于很多Java初學(xué)者來說,前面兩個比較常用,ArrayList查詢效率比較高(底層是數(shù)組實現(xiàn)),而LinkedList的增刪效率比較高(底層是雙向鏈表實現(xiàn))。那么Vector是什么呢?它和ArrayList、LinkedList一樣,支持有序可重復(fù)地存放單列數(shù)據(jù)。它底層實現(xiàn)和ArrayList類似,都是數(shù)組實現(xiàn),因此在技術(shù)面試中, 面試官比較喜歡拿ArrayList和Vector進(jìn)行比較。盡管Vector在Java1.2之后進(jìn)行了優(yōu)化更新,但是Java官方還是推薦在不需要考慮線程安全的情況下,優(yōu)先使用ArrayList。
二、Vector和ArrayList的對比
那么,Vector和ArrayList既然都是數(shù)組實現(xiàn),它們到底有什么區(qū)別呢?通過對比它們的源碼,可以總結(jié)出以下兩個區(qū)別:
(1) Vector的所有方法都是有synchronized關(guān)鍵字的,即每一個方法都是同步的,所以在使用起來效率會非常低,但是保證了線程安全;而ArrayList的全部方法都是非同步的,所以相對Vector的效率會更高,所以它是線程不安全的。
(2) ArrayList在每次擴(kuò)容時都是增加當(dāng)前容量的1.5倍,而Vector在擴(kuò)容時都是增加當(dāng)前容量的兩倍。
綜上,Vector在增刪改查等API上的實現(xiàn)都是和ArrayList類似甚至是相同的,所以如果你看了ArrayList的源碼,那么Vector的源碼你肯定是一下就看懂了,如果你還沒看ArrayList的源碼,請移步到《Java容器類源碼-ArrayList的最全的源碼分析》。所以在不需要考慮線程安全時,Java官方推薦我們使用ArrayList,那么,如果線程不安全時呢?我們應(yīng)該怎么選擇?我們都知道,Java在Collections類中給我們提供了同步ArrayList的方法public static <T> List<T> synchronizedList(List<T> list)。它可以幫助我們實現(xiàn)同步ArrayList,但是你通過看synchronizedList的實現(xiàn)就會知道,它其實是創(chuàng)建了一個新的類叫做SynchronizedList,它其實只是對ArrayList的增刪改查等常用方法加了synchronized字段,所以它的效率其實和Vector是一樣的,這個也在我們后面講到的subList()源碼里面得到印證,不信,我們在代碼里面測試一下:
/**
* 測試使用Collections.synchronizedList調(diào)用增、刪、改三個API操作50000個數(shù)據(jù),求100次的平均時間
*
*/publicclassQTest{publicstaticvoidmain(String[] args){longtotalTime =0;for(inti =0; i <100; i++) {totalTime +=newQTest().getTime();}System.out.println("Collections.synchronizedList() 平均耗時:"+ (totalTime /100)); }publiclonggetTime(){Listlist= Collections.synchronizedList(newArrayList());longstartTime = System.currentTimeMillis();for(inti =0; i <50000; i++) {list.add(i *10);// 增加}for(inti =0; i <50000; i++) {// 修改list.set(i, i);}for(inti =0; i
* 測試使用Vector調(diào)用增、刪、改三個API操作50000個數(shù)據(jù),求100次的平均時間
*
*/publicclassPTest{publicstaticvoidmain(String[] args){longtotalTime =0;for(inti =0; i <100; i++) {totalTime +=newQTest().getTime();} System.out.println("vector 平均耗時:"+ (totalTime /100));}
publiclonggetTime(){Vectorvector=newVector<>();longnStartTime = System.currentTimeMillis();for(inti =0; i <100000; i++) {vector.add(i *10);// 增加}for(inti =0; i <100000; i++) {// 修改vector.set(i, i);}for(inti =0; i
這兩段代碼其實就是對同步的ArrayList進(jìn)行增、刪、改50000條數(shù)據(jù),并重復(fù)100次,求平均時間。通過運行,在我的電腦(每臺電腦的運行速度不一樣)里Collections.synchronizedList的100次平均消耗時間是:129ms,而Vector的100次平均消耗時間是:130ms。在需要考慮線程安全時,你是用Vector和Collections.synchronizedList初始化的ArrayList大概效率是差不多的。所以,Vector也并非毫無用武之地,那么這次我們就一起探究一下Vector的源碼。
三、源碼解讀
1. 繼承、實現(xiàn)
extends:AbstractListimplements:List, RandomAccess, Cloneable, java.io.Serializable
2. 全局變量
(1) 存放數(shù)據(jù)的數(shù)組
protected Object[] elementData;
(2) 存放數(shù)量
protected int elementCount;
(3) 容量增量
protected int capacityIncrement;
3. 構(gòu)造方法
(1) 不帶參數(shù)的構(gòu)造方法
publicVector(){this(10);}
(2) 帶初始化容量大小的構(gòu)造方法
/**
* @param initialCapacity 初始化容量大小
*/publicVector(intinitialCapacity){this(initialCapacity,0);}
(3) 帶初始化容量和容量增量的構(gòu)造方法
/** *@paraminitialCapacity初始化容量大小 *@paramcapacityIncrement 容量增量 */publicVector(intinitialCapacity,intcapacityIncrement){super();if(initialCapacity <0)thrownewIllegalArgumentException("Illegal Capacity: "+ initialCapacity);this.elementData =newObject[initialCapacity];this.capacityIncrement = capacityIncrement;}(4) 帶Colleciton參數(shù)的構(gòu)造方法/** *@paramc 將c轉(zhuǎn)為Vector */publicVector(Collection 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);}
4. 方法
(1) public synchronized void copyInto(Object[] anArray)
源碼解釋:
通過JNI調(diào)用c++庫的arraycopy方法,實現(xiàn)將anArray數(shù)組復(fù)制到當(dāng)前的Vector。
publicsynchronizedvoidcopyInto(Object[] anArray){ System.arraycopy(elementData,0, anArray,0, elementCount); }
(2) public synchronized void trimToSize()
源碼解釋:
用以優(yōu)化Vector的內(nèi)存,我們都知道,Vector的每次容量增量是當(dāng)前大小的2倍,但是當(dāng)我們沒法用完申請的這么多內(nèi)存時,我們可以通過調(diào)用這個方法用以將不需要的內(nèi)存釋放掉。
publicsynchronizedvoidtrimToSize(){ modCount++;// 修改次數(shù)增加intoldCapacity = elementData.length;// 獲取到當(dāng)前的申請的內(nèi)存大小if(elementCount < oldCapacity) {// 如果當(dāng)前存放的數(shù)量比申請的內(nèi)存要少elementData = Arrays.copyOf(elementData, elementCount);// 重新為這個數(shù)組申請elementCount大小內(nèi)存,并存放這些數(shù)據(jù)} }
(3) public synchronized void ensureCapacity(int minCapacity)
源碼解釋:
當(dāng)要擴(kuò)容時,會調(diào)用此方法,保證當(dāng)前容量能存放得下所需要存放的元素數(shù)量。如果不夠時,會調(diào)用grow()方法進(jìn)行擴(kuò)容。
publicsynchronizedvoidensureCapacity(intminCapacity){if(minCapacity >0) { modCount++; ensureCapacityHelper(minCapacity); } }privatevoidensureCapacityHelper(intminCapacity){// overflow-conscious codeif(minCapacity - elementData.length >0) grow(minCapacity);// 如果當(dāng)前容量比數(shù)組的長度要小時,調(diào)用grow擴(kuò)容}privatestaticfinalintMAX_ARRAY_SIZE = Integer.MAX_VALUE -8;/** * Vector的擴(kuò)容方法, 每次擴(kuò)容至2倍 *@paramminCapacity */privatevoidgrow(intminCapacity){// overflow-conscious codeintoldCapacity = elementData.length;// 獲取到數(shù)組的長度intnewCapacity = oldCapacity + ((capacityIncrement >0) ? capacityIncrement : oldCapacity);//如果沒有初始化capacityIncrement,則增加至兩倍if(newCapacity - minCapacity <0) newCapacity = minCapacity;if(newCapacity - MAX_ARRAY_SIZE >0)// 如果擴(kuò)容后的容量超過了最大容量newCapacity = hugeCapacity(minCapacity);// 調(diào)用hugeCapacity方法elementData = Arrays.copyOf(elementData, newCapacity);// 將數(shù)組復(fù)制到擴(kuò)容后的新內(nèi)存中去}privatestaticinthugeCapacity(intminCapacity){if(minCapacity <0)// overflowthrownewOutOfMemoryError();return(minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
(4) public synchronized void setSize(int newSize)
源碼解釋:
修改容量,當(dāng)newSize比數(shù)組的長度要大時,將其復(fù)制到新的內(nèi)存區(qū)域,如果要小的話,則從newSize位置到數(shù)組的最后一個位置的所有元素置為空。
publicsynchronizedvoidsetSize(intnewSize){ modCount++;if(newSize > elementCount) { ensureCapacityHelper(newSize); }else{for(inti = newSize ; i < elementCount ; i++) { elementData[i] =null; } } elementCount = newSize; }
(5) public synchronized int capacity()
源碼解釋:
返回數(shù)組長度,即申請內(nèi)存的長度。
publicsynchronizedintcapacity(){returnelementData.length; }
(6) public synchronized int size()
源碼解釋:
返回數(shù)組已經(jīng)使用的長度,即存放的數(shù)據(jù)個數(shù)。
publicsynchronizedintsize(){returnelementCount; }
(7) public synchronized boolean isEmpty()
源碼解釋:
判空,如果數(shù)量為0,即為empty。
publicsynchronizedbooleanisEmpty(){returnelementCount ==0; }
(8) public Enumeration<E> elements()
源碼解釋:
返回一個Enumeration對象的序列。Enumeration只有兩個方法,hasMoreElements()和nextElement(),它只能從首個元素遍歷到最后一個元素,并不能根據(jù)位置拿到具體的元素。
publicEnumeration elements() {returnnewEnumeration() {intcount=0;publicbooleanhasMoreElements() {returncount< elementCount; }publicE nextElement() {synchronized(Vector.this) {if(count< elementCount) {returnelementData(count++); } }thrownewNoSuchElementException("Vector Enumeration"); } }; }
(9) public boolean contains(Object o)
源碼解釋:
是否包含對象o。調(diào)用indexOf判斷是否存在。
publicbooleancontains(Object o){returnindexOf(o,0) >=0; }publicintindexOf(Object o){returnindexOf(o,0); }
(10) public synchronized int indexOf(Object o, int index)
源碼解釋:
判斷o是否為空,如果為空,則遍歷是否存在值為空的元素;不為空,判斷是否存在和o相等的元素。
publicsynchronizedintindexOf(Object o,intindex) {if(o ==null) {for(inti =index; i < elementCount ; i++)if(elementData[i]==null)returni; }else{for(inti =index; i < elementCount ; i++)if(o.equals(elementData[i]))returni; }return-1; }
(11) public synchronized int lastIndexOf
源碼解釋:
獲取該元素所處的最后一個位置,不存在則返回-1
publicsynchronizedintlastIndexOf(Object o){returnlastIndexOf(o, elementCount-1); }publicsynchronizedintlastIndexOf(Object o,intindex){if(index >= elementCount)thrownewIndexOutOfBoundsException(index +" >= "+ elementCount);if(o ==null) {for(inti = index; i >=0; i--)if(elementData[i]==null)returni; }else{for(inti = index; i >=0; i--)if(o.equals(elementData[i]))returni; }return-1; }
(12) public synchronized E elementAt(int index)
源碼解釋:
返回這個位置的元素。其實就是判斷數(shù)組的index位置是否有元素
publicsynchronized E elementAt(intindex) {if(index>= elementCount) {thrownewArrayIndexOutOfBoundsException(index+" >= "+ elementCount); }returnelementData(index); } E elementData(intindex) {return(E) elementData[index]; }
(13) public synchronized E firstElement()
源碼解釋:
返回數(shù)組第0個位置的元素。
publicsynchronizedEfirstElement(){if(elementCount ==0) {thrownewNoSuchElementException(); }returnelementData(0); }
(14) public synchronized E lastElement()
源碼解釋:
返回數(shù)組最后一個位置的元素。
publicsynchronizedElastElement(){if(elementCount ==0) {thrownewNoSuchElementException(); }returnelementData(elementCount -1); }
(15) public synchronized void setElementAt(E obj, int index)
源碼解釋:
修改第index位置的值為obj。其實就是數(shù)組賦值。
publicsynchronizedvoidsetElementAt(E obj,intindex) {if(index>= elementCount) {thrownewArrayIndexOutOfBoundsException(index+" >= "+ elementCount); } elementData[index] = obj; }
(16) public synchronized void removeElementAt(int index)
源碼解釋:
獲取到index位置后有多少個元素,并將index位置后面的元素復(fù)制到index位置前的后面,再將index位置置空。復(fù)制操作通過JNI實現(xiàn)。
publicsynchronizedvoidremoveElementAt(intindex) { modCount++;if(index>= elementCount) {thrownewArrayIndexOutOfBoundsException(index+" >= "+ elementCount); }elseif(index<0) {thrownewArrayIndexOutOfBoundsException(index); }intj = elementCount -index-1;// 獲取第index位置后有多少個元素if(j >0) { System.arraycopy(elementData,index+1, elementData,index, j);// 將emlementData[j, elementCount]復(fù)制到elementData[0, index]的后面} elementCount--; elementData[elementCount] =null;// 等待GC}
(17) public synchronized void insertElementAt(E obj, int index)
源碼解釋:
將index位置后的元素復(fù)制到原數(shù)組的index+1位置后的地方,并在index位置賦值obj。
publicsynchronizedvoidinsertElementAt(E obj,intindex) { modCount++;if(index> elementCount) {thrownewArrayIndexOutOfBoundsException(index+" > "+ elementCount); } ensureCapacityHelper(elementCount +1);// 判斷是否需要擴(kuò)容System.arraycopy(elementData,index, elementData,index+1, elementCount -index);// 將elementData[index+1, elementCount]復(fù)制到elementData[index+1, elementCount +1]位置,elementData[index] = obj;// 在index位置賦值objelementCount++; }
(18) public synchronized void addElement(E obj)
源碼解釋:
在數(shù)組最后添加數(shù)據(jù)obj。先擴(kuò)容,再通過數(shù)組賦值。
publicsynchronized voidaddElement(E obj) { modCount++;ensureCapacityHelper(elementCount +1);elementData[elementCount++] = obj;}
(19) public synchronized boolean removeElement(Object obj)
源碼解釋:
移除元素。先獲取到移除元素在數(shù)組的位置,然后調(diào)用removeElementAt方法移除元素。
publicsynchronizedbooleanremoveElement(Object obj){ modCount++;inti = indexOf(obj);if(i >=0) { removeElementAt(i);returntrue; }returnfalse; }
(20) public synchronized void removeAllElements()
源碼解釋:
移除所有元素。即將所有元素置為null,等待gc。
publicsynchronizedvoidremoveAllElements(){ modCount++;// Let gc do its workfor(inti =0; i < elementCount; i++) elementData[i] =null;? elementCount =0; }
(21) public synchronized E get(int index)
源碼解釋:
獲取index位置的元素。
publicsynchronized E get(intindex) {if(index>= elementCount)thrownewArrayIndexOutOfBoundsException(index);returnelementData(index); }
(22) public synchronized E set(int index, E element)
源碼解釋:
修改index位置的值為element。實現(xiàn)原理也是直接數(shù)組賦值。
public synchronized E set(intindex,Eelement) {if(index>= elementCount) throw new ArrayIndexOutOfBoundsException(index);? E oldValue = elementData(index); elementData[index] =element; return oldValue; }
(23) public synchronized boolean add(E e)
源碼解釋:
在最后位置新增元素e。先判斷是否需要擴(kuò)容,然后賦值。實現(xiàn)原理和addElement是一樣的。
publicsynchronized boolean add(E e) { modCount++;ensureCapacityHelper(elementCount +1);elementData[elementCount++] = e;return true;}
(24) public boolean remove(Object o)
源碼解釋:
移除元素,和removeElement方法一樣。
public boolean remove(Object o) {
return removeElement(o);
}
(25) public void add(int index, E element)
源碼解釋:
添加元素,和insertElementAt方法一樣。
public void add(intindex,Eelement) { insertElementAt(element,index); }
(26) public synchronized E remove(int index)
源碼解釋:
移除index位置的元素。實現(xiàn)思路和removeElementAt類似。
public synchronized E remove(intindex) {?
modCount++;
if(index>= elementCount)thrownewArrayIndexOutOfBoundsException(index);?
E oldValue = elementData(index);
// 獲取到舊值
intnumMoved = elementCount -index-1;
// index位置后面元素的個數(shù)
if(numMoved >0) System.arraycopy(elementData,index+1, elementData,index, numMoved);
// 將elementData[index+1, elementCount]移到element[0, index]后elementData[--elementCount] =null;
// Let gc do its workreturnoldValue;?
}
(27) public void clear()
源碼解釋:
移除所有元素,直接調(diào)用removeAllElements()。
publicvoidclear(){ removeAllElements(); }
(28) public synchronized boolean containsAll(Collection<?> c)
源碼解釋:
判斷是否包含集合c的所有元素。調(diào)用AbstractCollection的實現(xiàn),代碼也很簡單,不贅敘。
publicsynchronizedbooleancontainsAll(Collection<?> c){returnsuper.containsAll(c); }publicbooleancontainsAll(Collection<?> c){for(Object e : c)if(!contains(e))returnfalse;returntrue; }
(29) public synchronized boolean addAll(Collection<? extends E> c)
源碼解釋:
把集合c復(fù)制到當(dāng)前數(shù)組的末尾。先判斷是否需要擴(kuò)容,然后調(diào)用JNI的arraycopy實現(xiàn)復(fù)制。
publicsynchronized boolean addAll(Collection<? extends E> c) { modCount++;Object[] a = c.toArray(); int numNew = a.length; ensureCapacityHelper(elementCount + numNew);System.arraycopy(a,0, elementData, elementCount, numNew); elementCount += numNew; return numNew !=0; }
(30) public synchronized boolean removeAll(Collection<?> c)
源碼解釋:
將包含集合c的所有元素移除。調(diào)用AbstractCollection的實現(xiàn),代碼也很簡單,不贅敘。
publicbooleanremoveAll(Collection c) { Objects.requireNonNull(c);booleanmodified =false; Iteratorit= iterator();while(it.hasNext()) {if(c.contains(it.next())) {it.remove(); modified =true; } } returnmodified; }
(31) public synchronized boolean retainAll(Collection<?> c)
源碼解釋:
將數(shù)組中不是c中包含的元素全部移除。調(diào)用AbstractCollection的實現(xiàn),代碼也很簡單,不贅敘。
publicsynchronizedbooleanretainAll(Collection<?> c){returnsuper.retainAll(c); }publicbooleanretainAll(Collection<?> c){ Objects.requireNonNull(c);booleanmodified =false; Iterator it = iterator();while(it.hasNext()) {if(!c.contains(it.next())) { it.remove(); modified =true; } }returnmodified; }
(32) public synchronized boolean addAll(int index, Collection<? extends E> c)
源碼解釋:
在index位置插入集合c。實現(xiàn)原理和在某個位置插入元素原理一樣,不贅敘。
publicsynchronizedbooleanaddAll(intindex, Collection c) { modCount++;if(index<0||index> elementCount)thrownewArrayIndexOutOfBoundsException(index);? Object[] a = c.toArray();intnumNew = a.length; ensureCapacityHelper(elementCount + numNew);intnumMoved = elementCount -index;if(numMoved >0) System.arraycopy(elementData,index, elementData,index+ numNew, numMoved);? System.arraycopy(a,0, elementData,index, numNew); elementCount += numNew;returnnumNew !=0; }
(33) public synchronized List<E> subList(int fromIndex, int toIndex)
源碼解釋:
調(diào)用父類的subList,然后通過Collections.synchronizedList來保證子List是同步的,這也就印證了我們前面所說的Collections.synchronizedList初始化的ArrayList和Vector是一樣效率的,因為它們的同步方式都是一樣的,而增刪改查這些操作對于它們兩個來說都是一樣的原理,所以可以知道它們的效率是一樣的。
publicsynchronizedListsubList(intfromIndex,inttoIndex){returnCollections.synchronizedList(super.subList(fromIndex, toIndex),this); }
(34) protected synchronized void removeRange(int fromIndex, int toIndex)
源碼解釋:
將某個范圍的數(shù)據(jù)移除。實現(xiàn)原理和刪除某個位置的元素原理是一樣的,不贅敘。
protectedsynchronizedvoidremoveRange(intfromIndex,inttoIndex){ modCount++;intnumMoved = elementCount - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved);// Let gc do its workintnewElementCount = elementCount - (toIndex-fromIndex);while(elementCount != newElementCount) elementData[--elementCount] =null; }
(35) public synchronized ListIterator<E> listIterator(int index)
源碼解釋:
返回一個從index位置開始的LIstIterator,方便我們遍歷Vector,關(guān)于ListIterator在《Java容器類源碼-LinkedList的最全的源碼分析》已經(jīng)詳說,這里不贅敘。
publicsynchronized ListIterator listIterator(intindex) {if(index<0||index> elementCount)thrownewIndexOutOfBoundsException("Index: "+index);returnnewListItr(index); }
(36) public synchronized ListIterator<E> listIterator()
源碼解釋:
返回一個從0位置開始的ListIterator,不贅敘。
publicsynchronizedListIteratorlistIterator(){returnnewListItr(0); }
(37) public synchronized Iterator<E> iterator()
源碼解釋:
返回一個Iterator實現(xiàn)類Itr。有人會問ListIterator和Itr有什么區(qū)別嗎?其實ListIterator是Itr的子類,它在Itr的基礎(chǔ)上再增加了一些接口,例如hasPrevious(),nextIndex()等,所以如果覺得Iterator不能滿足你的需求,可以看一下ListIterator里面提供的API。
publicsynchronizedIteratoriterator(){returnnewItr(); }
(38) public Spliterator<E> spliterator()
源碼解釋:
實例化一個VectorSpliterator對象,并返回。VectorSpliterator是JDK1.8之后LinkedList新增的內(nèi)部類,因為用得比較少,我就不在這里班門弄斧了,大家有需要可以自行深入研究。
publicSpliteratorspliterator(){returnnewVectorSpliterator<>(this,null,0,-1,0); }
四、總結(jié)
看完了Vector的源碼,我覺得我們需要學(xué)到比較重要的幾點。首先是開頭所說的Vector和ArrayList的區(qū)別,這里就不重復(fù)了。第二個就是我們通過subList這個實現(xiàn)可以看到,它的子序列其實也是通過Collections.synchronizedList來初始化子序列并返回的,所以其實Collections.synchronizedList初始化的ArrayList實現(xiàn)同步的原理和Vector是一樣的,而ArrayList和Vector的底層都是數(shù)組,常規(guī)的增刪改查操作是一樣的,所以我們可以確定Vector和實現(xiàn)了同步的ArrayList在數(shù)據(jù)操作時的效率是相近的,所以我覺得我們并不需要糾結(jié)在考慮線程安全時到底是用Collections.synchronizedList初始化的ArrayList還是Vector。第三個就是需要了解到Vector的增刪改查實現(xiàn)原理,它的api核心可以說就是這幾個方法了,所有其他api都是圍繞這幾個方法來進(jìn)行擴(kuò)展。
---------------------
每天都在分享文章,也每天都有人想要我出來給大家分享下怎么去學(xué)習(xí)Java。大家都知道,我們是學(xué)Java全棧的,大家就肯定以為我有全套的Java系統(tǒng)教程。沒錯,我是有Java全套系統(tǒng)教程,進(jìn)扣裙【47】974【9726】所示,進(jìn)群的時候記得表明自己想要學(xué)習(xí)什么,不要用小號,這樣小編才好給你們發(fā)定向資源,今天小編就免費送!~
“我們相信人人都可以成為一個程序員,現(xiàn)在開始,找個師兄,帶你入門,學(xué)習(xí)的路上不再迷茫。這里是ja+va修真院,初學(xué)者轉(zhuǎn)行到互聯(lián)網(wǎng)行業(yè)的聚集地。" public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index); // 獲取到舊值
int numMoved = elementCount - index - 1; // index位置后面元素的個數(shù)
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved); // 將elementData[index+1, elementCount]移到element[0, index]后
elementData[--elementCount] = null; // Let gc do its work
return oldValue;
}
(27) public void clear(