ArrayList源碼分析
?
?? ArrayList是以數(shù)組為基礎(chǔ)實(shí)現(xiàn)的一個(gè)動(dòng)態(tài)數(shù)組容器,通過(guò)以下的代碼分析可知,一方面在ArrayList中添加或者刪除元素(除了在數(shù)組容器末尾添加或者刪除元素),是需要移動(dòng)大量元素的借助System.arraycopy()來(lái)實(shí)現(xiàn)拷貝移動(dòng),另一方面,由于數(shù)組實(shí)現(xiàn)基礎(chǔ),可依靠數(shù)組下標(biāo),可以實(shí)現(xiàn)隨機(jī)訪問(wèn),當(dāng)然查找具體的元素,還是需要循環(huán)去查找的,再者ArrayList不是thread-safe的,在代碼中無(wú)論是add,remove,get,都沒(méi)有任何同步措施,在多線程環(huán)境下需要自己確保thread-safe。由此可知ArrayList適用于在任意位置添加,刪除元素不多,要求隨機(jī)訪問(wèn)的應(yīng)用場(chǎng)景。
?
? 代碼分析主要羅列:ArrayList構(gòu)造函數(shù),remove(), add(), get()
?
1.ArrayList構(gòu)造函數(shù)
?
?? private transient E[] elementData;ArrayList使用對(duì)象數(shù)組元素來(lái)作為內(nèi)部實(shí)現(xiàn)的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)。
?
- //ArrayList是以數(shù)組為基礎(chǔ)實(shí)現(xiàn)的,采用的泛型編程,數(shù)組元素都是Object類型 ??
- //初始化時(shí)主要是構(gòu)造指定大小的數(shù)組,用于存儲(chǔ)對(duì)象元素 ??
- public ?ArrayList( int ?initialCapacity){??
- ?????? super ();??
- ?????? if ?(initialCapacity?<? 0 )??
- ?????????? throw ? new ?IllegalArgumentException( "Illegal?Capacity:?" +??
- ?????????????????????????????????????????????initialCapacity);??
- ?????? this .elementData?=?(E[]) new ?Object[initialCapacity];??
- }??
- //ArrayList是以數(shù)組為基礎(chǔ)實(shí)現(xiàn)的,采用的泛型編程,數(shù)組元素都是Object類型 ??
- //初始化時(shí)主要是構(gòu)造指定大小的數(shù)組,用于存儲(chǔ)對(duì)象元素 ??
- public ?ArrayList( int ?initialCapacity){??
- ?????? super ();??
- ?????? if ?(initialCapacity?<? 0 )??
- ?????????? throw ? new ?IllegalArgumentException( "Illegal?Capacity:?" +??
- ?????????????????????????????????????????????initialCapacity);??
- ?????? this .elementData?=?(E[]) new ?Object[initialCapacity];??
- }??
?
- //默認(rèn)情況下ArrayList實(shí)現(xiàn)依賴的數(shù)組長(zhǎng)度為10 ??
- ??? public ?ArrayList()?{??
- ???????? this ( 10 );??
- ???}??
- //默認(rèn)情況下ArrayList實(shí)現(xiàn)依賴的數(shù)組長(zhǎng)度為10 ??
- ??? public ?ArrayList()?{??
- ???????? this ( 10 );??
- ???}??
??
?
?
- //使用另一個(gè)集合中的元素來(lái)初始化當(dāng)前的List ??
- ? public ?ArrayList(Collection<?? extends ?E>?c)?{??
- ??????size?=?c.size();??
- ?????? //?Allow?10%?room?for?growth ??
- ??????elementData?=?(E[]) new ?Object[??
- ????????????????????( int )Math.min((size*110L)/ 100 ,Integer.MAX_VALUE)];???
- ??????c.toArray(elementData);??
- ??}??
- //使用另一個(gè)集合中的元素來(lái)初始化當(dāng)前的List ??
- ? public ?ArrayList(Collection<?? extends ?E>?c)?{??
- ??????size?=?c.size();??
- ?????? //?Allow?10%?room?for?growth ??
- ??????elementData?=?(E[]) new ?Object[??
- ????????????????????( int )Math.min((size*110L)/ 100 ,Integer.MAX_VALUE)];???
- ??????c.toArray(elementData);??
- ??}??
2.
ensureCapaciyt(int) | add(E) | add(int, E)分析
?
?? ensureCapacity主要用來(lái)實(shí)現(xiàn)數(shù)組的動(dòng)態(tài)擴(kuò)容,每次擴(kuò)容為原來(lái)大小的1.5倍,在add操作前調(diào)用,以確保數(shù)組容量夠用。
?
- public ? void ?ensureCapacity( int ?minCapacity)?{??
- ??
- ????modCount++;??
- ???? int ?oldCapacity?=?elementData.length;??
- ??????????
- ???????? //如果當(dāng)前數(shù)組的實(shí)際容量(oldCapacity)比當(dāng)前要求的容量要小(minCapacity) ??
- ???????? //就需要進(jìn)行擴(kuò)容,申請(qǐng)新的數(shù)組空間,大小為minCapacity,并將原來(lái)數(shù)組空間中的元素拷貝 ??
- ???????? //到新的數(shù)組空間當(dāng)中。???????? ??
- ???? if ?(minCapacity?>?oldCapacity)?{??
- ????????Object?oldData[]?=?elementData;??
- ????????????
- ???????????? //擴(kuò)容因子為:1.5倍左右,每次需要擴(kuò)容時(shí),會(huì)將空間擴(kuò)展為原來(lái)的1.5倍大小 ??
- ???????? int ?newCapacity?=?(oldCapacity?*? 3 )/ 2 ?+? 1 ;??
- ??
- ???????????? if ?(newCapacity?<?minCapacity)??
- ????????newCapacity?=?minCapacity;??
- ??
- ????????elementData?=?(E[]) new ?Object[newCapacity];??
- ????????????????
- ???????????? //將數(shù)組元素轉(zhuǎn)移到新申請(qǐng)的數(shù)組空間當(dāng)中 ??
- ????????System.arraycopy(oldData,? 0 ,?elementData,? 0 ,?size);??
- ????}??
- }??
- public ? void ?ensureCapacity( int ?minCapacity)?{??
- ??
- ????modCount++;??
- ???? int ?oldCapacity?=?elementData.length;??
- ??????????
- ???????? //如果當(dāng)前數(shù)組的實(shí)際容量(oldCapacity)比當(dāng)前要求的容量要小(minCapacity) ??
- ???????? //就需要進(jìn)行擴(kuò)容,申請(qǐng)新的數(shù)組空間,大小為minCapacity,并將原來(lái)數(shù)組空間中的元素拷貝 ??
- ???????? //到新的數(shù)組空間當(dāng)中。???????? ??
- ???? if ?(minCapacity?>?oldCapacity)?{??
- ????????Object?oldData[]?=?elementData;??
- ????????????
- ???????????? //擴(kuò)容因子為:1.5倍左右,每次需要擴(kuò)容時(shí),會(huì)將空間擴(kuò)展為原來(lái)的1.5倍大小 ??
- ???????? int ?newCapacity?=?(oldCapacity?*? 3 )/ 2 ?+? 1 ;??
- ??
- ???????????? if ?(newCapacity?<?minCapacity)??
- ????????newCapacity?=?minCapacity;??
- ??
- ????????elementData?=?(E[]) new ?Object[newCapacity];??
- ????????????????
- ???????????? //將數(shù)組元素轉(zhuǎn)移到新申請(qǐng)的數(shù)組空間當(dāng)中 ??
- ????????System.arraycopy(oldData,? 0 ,?elementData,? 0 ,?size);??
- ????}??
- }??
? add(E)操作是向集合ArrayList中存儲(chǔ)元素,在當(dāng)前數(shù)組容器的尾部添加,不需要移動(dòng)元素,返回true。
?
- public ? boolean ?add(E?o)?{??
- ???????? //調(diào)用ensureCapacity確保當(dāng)前容量不小于(size?+?1),size為容器中當(dāng)前存儲(chǔ)的實(shí)際元素個(gè)數(shù). ??
- ????ensureCapacity(size?+? 1 );???
- ???????? //將對(duì)象引用o保存到數(shù)組容器中,并++size. ??
- ????elementData[size++]?=?o;??
- ???? return ? true ;??
- }??
- public ? boolean ?add(E?o)?{??
- ???????? //調(diào)用ensureCapacity確保當(dāng)前容量不小于(size?+?1),size為容器中當(dāng)前存儲(chǔ)的實(shí)際元素個(gè)數(shù). ??
- ????ensureCapacity(size?+? 1 );???
- ???????? //將對(duì)象引用o保存到數(shù)組容器中,并++size. ??
- ????elementData[size++]?=?o;??
- ???? return ? true ;??
- }??
add(int , E)在ArrayList中的指定位置index,保存對(duì)象element.
?
- public ? void ?add( int ?index,?E?element)?{??
- ??
- ???????? //檢測(cè)指定位置的合法性 ??
- ???? if ?(index?>?size?||?index?<? 0 )??
- ???????? throw ? new ?IndexOutOfBoundsException(??
- ???????? "Index:?" +index+ ",?Size:?" +size);??
- ??
- ????ensureCapacity(size+ 1 );??
- ??????????
- ???????? //將數(shù)組容器elementData中從index位置開(kāi)始的元素,依次往后移動(dòng)一個(gè)位置 ??
- ???????? //也就是說(shuō)經(jīng)過(guò)arraycopy()后,index位置被空出來(lái) ??
- ????System.arraycopy(elementData,?index,?elementData,?index?+? 1 ,??
- ?????????????size?-?index);??
- ??
- ???????? //將對(duì)象element存儲(chǔ)到數(shù)組容器的index位置上 ??
- ????elementData[index]?=?element;??
- ????size++;??
- }??
- public ? void ?add( int ?index,?E?element)?{??
- ??
- ???????? //檢測(cè)指定位置的合法性 ??
- ???? if ?(index?>?size?||?index?<? 0 )??
- ???????? throw ? new ?IndexOutOfBoundsException(??
- ???????? "Index:?" +index+ ",?Size:?" +size);??
- ??
- ????ensureCapacity(size+ 1 );??
- ??????????
- ???????? //將數(shù)組容器elementData中從index位置開(kāi)始的元素,依次往后移動(dòng)一個(gè)位置 ??
- ???????? //也就是說(shuō)經(jīng)過(guò)arraycopy()后,index位置被空出來(lái) ??
- ????System.arraycopy(elementData,?index,?elementData,?index?+? 1 ,??
- ?????????????size?-?index);??
- ??
- ???????? //將對(duì)象element存儲(chǔ)到數(shù)組容器的index位置上 ??
- ????elementData[index]?=?element;??
- ????size++;??
- }??
3.
remove(int) | remove(Object) | fastRemove(int) | removeRange(int,int)分析
?
? remove(int)用于刪除ArrayList數(shù)組容器中指定位置int上的元素,并返回此元素.
?
- public ?E?remove( int ?index)?{??
- ??
- ????RangeCheck(index);??
- ??
- ????modCount++;??
- ??
- ????E?oldValue?=?elementData[index];??
- ???????? //numMoved需要移動(dòng)的元素個(gè)數(shù),也就是index后面的所有的元素個(gè)數(shù) ??
- ???? int ?numMoved?=?size?-?index?-? 1 ;??
- ??
- ???????? //將index后面的所有元素全部往前依次移動(dòng)一個(gè)位置 ??
- ???? if ?(numMoved?>? 0 )??
- ????????System.arraycopy(elementData,?index+ 1 ,?elementData,?index,??
- ?????????????????numMoved);??
- ??
- ???????? //經(jīng)過(guò)arraycopy的移位,數(shù)組容器的最個(gè)位置被騰空, ??
- ???????? //但是仍然持有某個(gè)對(duì)象的引用,需要把這個(gè)多余的引用置為null. ??
- ????????elementData[--size]?=? null ;? //?Let?gc?do?its?work ??
- ??
- ???? return ?oldValue;??
- }??
- public ?E?remove( int ?index)?{??
- ??
- ????RangeCheck(index);??
- ??
- ????modCount++;??
- ??
- ????E?oldValue?=?elementData[index];??
- ???????? //numMoved需要移動(dòng)的元素個(gè)數(shù),也就是index后面的所有的元素個(gè)數(shù) ??
- ???? int ?numMoved?=?size?-?index?-? 1 ;??
- ??
- ???????? //將index后面的所有元素全部往前依次移動(dòng)一個(gè)位置 ??
- ???? if ?(numMoved?>? 0 )??
- ????????System.arraycopy(elementData,?index+ 1 ,?elementData,?index,??
- ?????????????????numMoved);??
- ??
- ???????? //經(jīng)過(guò)arraycopy的移位,數(shù)組容器的最個(gè)位置被騰空, ??
- ???????? //但是仍然持有某個(gè)對(duì)象的引用,需要把這個(gè)多余的引用置為null. ??
- ????????elementData[--size]?=? null ;? //?Let?gc?do?its?work ??
- ??
- ???? return ?oldValue;??
- }??
remove(Object)刪除指定的對(duì)象Object,在數(shù)組容器中,需要特別處理null對(duì)象,過(guò)程都是,首先在數(shù)組容器中循環(huán)查找某個(gè)對(duì)象,如果查找到則調(diào)用fastRemove()進(jìn)行刪除。
?
- public ? boolean ?remove(Object?o)?{??
- ???? if ?(o?==? null )?{??
- ???????????? for ?( int ?index?=? 0 ;?index?<?size;?index++)??
- ???????? if ?(elementData[index]?==? null )?{??
- ????????????fastRemove(index);??
- ???????????? return ? true ;??
- ????????}??
- ????}? else ?{??
- ???????????? //注意比較兩個(gè)對(duì)象是否相等調(diào)用的是equals(), ??
- ???????????? //如果此類對(duì)象沒(méi)有重寫(xiě)equals() ??
- ???????????? //比較的是是否引用同一個(gè)對(duì)象,如果有重寫(xiě),將比較對(duì)象內(nèi)部狀態(tài). ??
- ???????? for ?( int ?index?=? 0 ;?index?<?size;?index++)??
- ???????? if ?(o.equals(elementData[index]))?{??
- ????????????fastRemove(index);??
- ???????????? return ? true ;??
- ????????}??
- ????????}??
- ???? return ? false ;??
- ????}??
- public ? boolean ?remove(Object?o)?{??
- ???? if ?(o?==? null )?{??
- ???????????? for ?( int ?index?=? 0 ;?index?<?size;?index++)??
- ???????? if ?(elementData[index]?==? null )?{??
- ????????????fastRemove(index);??
- ???????????? return ? true ;??
- ????????}??
- ????}? else ?{??
- ???????????? //注意比較兩個(gè)對(duì)象是否相等調(diào)用的是equals(), ??
- ???????????? //如果此類對(duì)象沒(méi)有重寫(xiě)equals() ??
- ???????????? //比較的是是否引用同一個(gè)對(duì)象,如果有重寫(xiě),將比較對(duì)象內(nèi)部狀態(tài). ??
- ???????? for ?( int ?index?=? 0 ;?index?<?size;?index++)??
- ???????? if ?(o.equals(elementData[index]))?{??
- ????????????fastRemove(index);??
- ???????????? return ? true ;??
- ????????}??
- ????????}??
- ???? return ? false ;??
- ????}??
fastRemove(int index)是相對(duì)于remove(int index)來(lái)說(shuō)的,因?yàn)椴恍枰M(jìn)行index合法性檢查和返回被刪除的元素,所以它可以稱為fast remove.fastRemove是private不能被外界訪問(wèn),只是在remove(Object o)中被調(diào)用,因?yàn)閞emove(Object o)在調(diào)用fastRemove()時(shí)候已經(jīng)確定了此對(duì)象的確存在才進(jìn)行fastRemove(),所以是安全的,不需要檢查。
?
- private ? void ?fastRemove( int ?index)?{??
- ???????modCount++;??
- ??????? int ?numMoved?=?size?-?index?-? 1 ;??
- ??????? if ?(numMoved?>? 0 )??
- ???????????System.arraycopy(elementData,?index+ 1 ,?elementData,?index,???
- ????????????????????????????numMoved);??
- ???????elementData[--size]?=? null ;? //?Let?gc?do?its?work ??
- ?}??
- private ? void ?fastRemove( int ?index)?{??
- ???????modCount++;??
- ??????? int ?numMoved?=?size?-?index?-? 1 ;??
- ??????? if ?(numMoved?>? 0 )??
- ???????????System.arraycopy(elementData,?index+ 1 ,?elementData,?index,???
- ????????????????????????????numMoved);??
- ???????elementData[--size]?=? null ;? //?Let?gc?do?its?work ??
- ?}??
removeRange(int, int)用于刪除數(shù)組容器中指定下標(biāo)范圍內(nèi)的元素
?
- ??? protected ? void ?removeRange( int ?fromIndex,? int ?toIndex)?{??
- modCount++;??
- int ?numMoved?=?size?-?toIndex;??
- ??????? //將從toIndex開(kāi)始的元素依次拷貝到fromIndex位置上。 ??
- ???????System.arraycopy(elementData,?toIndex,?elementData,?fromIndex,??
- ????????????????????????numMoved);??
- ??
- //?Let?gc?do?its?work ??
- ??????? //newSize為刪除指定范圍元素后,容器中所剩下的元素個(gè)數(shù)。 ??
- int ?newSize?=?size?-?(toIndex-fromIndex);??
- ??????? //將持有多余引用的元素位置(從size-1到newSize?-?1)置為null, ??
- ??????? //讓GC能夠及時(shí)回收垃圾對(duì)象. ??
- while ?(size?!=?newSize)??
- ????elementData[--size]?=? null ;??
- ???}??
- ??? protected ? void ?removeRange( int ?fromIndex,? int ?toIndex)?{??
- modCount++;??
- int ?numMoved?=?size?-?toIndex;??
- ??????? //將從toIndex開(kāi)始的元素依次拷貝到fromIndex位置上。 ??
- ???????System.arraycopy(elementData,?toIndex,?elementData,?fromIndex,??
- ????????????????????????numMoved);??
- ??
- //?Let?gc?do?its?work ??
- ??????? //newSize為刪除指定范圍元素后,容器中所剩下的元素個(gè)數(shù)。 ??
- int ?newSize?=?size?-?(toIndex-fromIndex);??
- ??????? //將持有多余引用的元素位置(從size-1到newSize?-?1)置為null, ??
- ??????? //讓GC能夠及時(shí)回收垃圾對(duì)象. ??
- while ?(size?!=?newSize)??
- ????elementData[--size]?=? null ;??
- ???}??
4.
get(int)
?
get(int)用于獲取ArrayList指定位置的元素,就是從數(shù)組中指定位置上取元素。
?
- public ?E?get( int ?index)?{??
- ??
- ???????? //RangeCheck(index)用于檢查index在數(shù)組元素中位置是否合法(必須index?<?size) ??
- ????RangeCheck(index);??
- ??
- ???? return ?elementData[index];??
- }??
- public ?E?get( int ?index)?{??
- ??
- ???????? //RangeCheck(index)用于檢查index在數(shù)組元素中位置是否合法(必須index?<?size) ??
- ????RangeCheck(index);??
- ??
- ???? return ?elementData[index];??
- }??
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
