欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

Java培訓之容器類ArrayList源碼分析

2018-04-23 10:27:44 1708瀏覽

本文是針對Java1.8的源代碼進行解析的,可能會和其他版本有所出入。



一、繼承和實現(xiàn)

繼承:AbstractList

實現(xiàn):List,RandomAccess,Cloneable,Serializable接口

publicclassArrayListextendsAbstractList
implementsList,RandomAccess,Cloneable,java.io.Serializable{
}

二、全局變量

1.默認容量

privatestaticfinalintDEFAULT_CAPACITY=10;

2.空的對象數(shù)組

privatestaticfinalObject[]EMPTY_ELEMENTDATA={};

3.默認的空數(shù)組

//無參構造函數(shù)創(chuàng)建的數(shù)組

privatestaticfinalObject[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA={};

4.存放數(shù)據(jù)的數(shù)組的緩存變量,不可序列化

transientObject[]elementData;

5.數(shù)組的大小

privateintsize;

三、構造方法

1.帶有容量initialCapacity的構造方法

源碼解釋:

publicArrayList(intinitialCapacity){

//如果初始化時ArrayList大小大于0

if(initialCapacity>0){

//new一個該大小的object數(shù)組賦給elementData

this.elementData=newObject[initialCapacity];

}elseif(initialCapacity==0){//如果大小為0

//將空數(shù)組賦給elementData

this.elementData=EMPTY_ELEMENTDATA;

}else{//小于0

//則拋出IllegalArgumentException異常

thrownewIllegalArgumentException("IllegalCapacity:"+

initialCapacity);

}

}

2.不帶參數(shù)的構造方法

源碼解釋:

publicArrayList(){

//直接將空數(shù)組賦給elementData

this.elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}

3.帶參數(shù)Collection的構造方法

源碼解釋:

參數(shù)c為一個Collection,Collection的實現(xiàn)類大概有以下幾種常用類型:

List:元素可以重復的容器

Set:元素不可重復的容器

Queue:結構是一個隊列,先進先出

這個構造方法的意思是,將一個Collection實現(xiàn)類的對象轉換為一個ArrayList,但是c容器裝的內(nèi)容

必須為ArrayList裝的內(nèi)容的子類。例如,將一個裝了String內(nèi)容的HashSet轉換為裝了String內(nèi)容的

ArrayList,使得ArrayList的大小和值數(shù)組都是HashSet的大小和值數(shù)組。具體實現(xiàn)如下代碼,首先調(diào)

用c(Collection的具體實現(xiàn)類)的toArray方法,具體大家可以看各個實現(xiàn)類的toArray方法,但是大

概意思都是將c容器轉換為object類型的數(shù)組,因為它們的返回值都是object[]。之于下面的兩個判斷

是當?shù)玫降膃lementData的類名不是Object類名的時候或者是長度為0的時候才會執(zhí)行。

publicArrayList(Collectionc){

elementData=c.toArray();

if((size=elementData.length)!=0){

if(elementData.getClass()!=Object[].class)

elementData=Arrays.copyOf(elementData,size,Object[].class);

}else{

//replacewithemptyarray.

this.elementData=EMPTY_ELEMENTDATA;

}

}

四、方法

1.trimToSize()

說明:將ArrayList的容量設置為當前size的大小。首先需要明確一個概念,ArrayList的size就是ArrayList的元素個數(shù),length是ArrayList申請的內(nèi)容空間長度。ArrayList每次都會預申請多一點空間,以便添加元素的時候不需要每次都進行擴容操作,例如我們的元素個數(shù)是10個,它申請的內(nèi)存空間必定會大于10,即length>size,而這個方法就是把ArrayList的內(nèi)存空間設置為size,去除沒有用到的null值空間。這也就是我們?yōu)槭裁疵看卧讷@取數(shù)據(jù)長度是都是調(diào)用list.size()而不是list.length()。

源碼解釋:首先modCount是從類java.util.AbstractList繼承的字段,這個字段主要是為了防止在多線程操作的情況下,List發(fā)生結構性的變化,什么意思呢?就是防止一個線程正在迭代,另外一個線程進行對List進行remove操作,這樣當我們迭代到最后一個元素時,很明顯此時List的最后一個元素為空,那么這時modCount就會告訴迭代器,讓其拋出異常ConcurrentModificationException。

如果沒有這一個變量,那么系統(tǒng)肯定會報異常ArrayIndexOutOfBoundsException,這樣的異常顯然不是應該出現(xiàn)的(這些運行時錯誤都是使用者的邏輯錯誤導致的,我們的JDK那么高端,不會出現(xiàn)使用錯誤,我們只拋出使用者造成的錯誤,而這個錯誤是設計者應該考慮的),為了避免出現(xiàn)這樣的異常,定義了檢查。

(引用自:郭無心,詳情可以看他在知乎的回答:https://www.zhihu.com/question/24086463/answer/64717159)。

publicvoidtrimToSize(){

modCount++;

//如果size小于length

if(size<elementData.length){

//重新將elementData設置大小為size

elementData=(size==0)

?EMPTY_ELEMENTDATA

:Arrays.copyOf(elementData,size);

}

}

2.size()

說明:返回ArrayList的大小

源碼解釋:直接返回size

publicintsize(){

returnsize;

}

3.isEmpty()

說明:返回是否為空

**源碼解釋:**直接返回判斷size==0

publicbooleanisEmpty(){

returnsize==0;

}

4.indexOf(Objecto)

說明:對象o在ArrayList中的下標位置,如果存在返回位置i,不存在返回-1

源碼解釋:遍歷ArrayList的大小,比較o和容器內(nèi)的元素,若相等,則返回位置i,若遍歷完都不相等,返回-1

publicintindexOf(Objecto){

if(o==null){

for(inti=0;i<size;i++)

if(elementData[i]==null)

returni;

}else{

for(inti=0;i<size;i++)

if(o.equals(elementData[i]))

returni;

}

return-1;

}

5.contains(Objecto)

說明:是否包含對象o

源碼解釋:調(diào)用indexOf()方法得到下標,存在則下標>=0,不存在為-1,即只要比較下標和0的大小即可。

publicbooleancontains(Objecto){

returnindexOf(o)>=0;

}

6.lastIndexOf(Objecto)

說明:返回容器內(nèi)出現(xiàn)o的最后一個位置

源碼解釋:從后向前遍歷,得到第一個出現(xiàn)對象o的位置,不存在則返回-1

publicintlastIndexOf(Objecto){

if(o==null){

for(inti=size-1;i>=0;i--)

if(elementData[i]==null)

returni;

}else{

for(inti=size-1;i>=0;i--)

if(o.equals(elementData[i]))

returni;

}

return-1;

}

7.clone()

說明:返回此ArrayList實例的淺表副本。

源碼解釋:

publicObjectclone(){

try{

//調(diào)用父類(翻看源碼可見是Object類)的clone方法得到一個ArrayList副本

ArrayListv=(ArrayList)super.clone();

//調(diào)用Arrays類的copyOf,將ArrayList的elementData數(shù)組賦值給副本的elementData數(shù)組

v.elementData=Arrays.copyOf(elementData,size);

v.modCount=0;

//返回副本v

returnv;

}catch(CloneNotSupportedExceptione){

thrownewInternalError(e);

}

}

8.toArray()

說明:ArrayList實例轉換為。

源碼解釋:直接調(diào)用Arrays類的copyOf。

publicObject[]toArray(){

returnArrays.copyOf(elementData,size);

}

9.toArray(T[]a)

說明:將ArrayList里面的元素賦值到一個數(shù)組中去

源碼解釋:如果a的長度小于ArrayList的長度,直接調(diào)用Arrays類的copyOf,返回一個比a數(shù)組長度要大的新數(shù)組,里面元素就是ArrayList里面的元素;如果a的長度比ArrayList的長度大,那么就調(diào)用System.arraycopy,將ArrayList的elementData數(shù)組賦值到a數(shù)組,然后把a數(shù)組的size位置賦值為空。

publicT[]toArray(T[]a){

if(a.length<size)

//Makeanewarrayofa'sruntimetype,butmycontents:

return(T[])Arrays.copyOf(elementData,size,a.getClass());

System.arraycopy(elementData,0,a,0,size);

if(a.length>size)

a[size]=null;

returna;

}

10.rangeCheck(intindex)

說明:測試index是否越界

源碼解釋:

privatevoidrangeCheck(intindex){

//如果下標超過ArrayList的數(shù)組長度

if(index>=size)

//拋出IndexOutOfBoundsException異常

thrownewIndexOutOfBoundsException(outOfBoundsMsg(index));

}

11.get(intindex)

說明:獲取index位置的元素

源碼解釋:先檢查是否越界,然后返回ArrayList的elementData數(shù)組index位置的元素。

publicEget(intindex){

//檢查是否越界

rangeCheck(index);

//返回ArrayList的elementData數(shù)組index位置的元素

returnelementData(index);

}

12.set(intindex,Eelement)

說明:設置index位置的元素值了element,返回該位置的之前的值

源碼解釋:

publicEset(intindex,Eelement){

//檢查是否越界

rangeCheck(index);

//調(diào)用elementData(index)獲取到當前位置的值

EoldValue=elementData(index);

//將element賦值到ArrayList的elementData數(shù)組的第index位置

elementData[index]=element;

returnoldValue;

}

13.ensureCapacityInternal(intminCapacity)

說明:得到最小擴容量

源碼解釋:

privatevoidensureCapacityInternal(intminCapacity){

if(elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA){

//獲取默認的容量和傳入?yún)?shù)的較大值

minCapacity=Math.max(DEFAULT_CAPACITY,minCapacity);

}

ensureExplicitCapacity(minCapacity);

}

14.ensureExplicitCapacity(intminCapacity)

說明:判斷是否需要擴容

源碼解釋:

privatevoidensureExplicitCapacity(intminCapacity){

modCount++;

//如果最小需要空間比elementData的內(nèi)存空間要大,則需要擴容

if(minCapacity-elementData.length>0)

grow(minCapacity);

}

15.grow()方法

說明:幫助ArrayList動態(tài)擴容的核心方法

源碼解釋:

//MAX_VALUE為231-1,MAX_ARRAY_SIZE就是獲取Java中int的最大限制,以防止越界

privatestaticfinalintMAX_ARRAY_SIZE=Integer.MAX_VALUE-8;

privatevoidgrow(intminCapacity){

//獲取到ArrayList中elementData數(shù)組的內(nèi)存空間長度

intoldCapacity=elementData.length;

//擴容至原來的1.5倍

intnewCapacity=oldCapacity+(oldCapacity>>1);

//再判斷一下新數(shù)組的容量夠不夠,夠了就直接使用這個長度創(chuàng)建新數(shù)組,

//不夠就將數(shù)組長度設置為需要的長度

if(newCapacity-minCapacity<0)

newCapacity=minCapacity;

//判斷有沒超過最大限制

if(newCapacity-MAX_ARRAY_SIZE>0)

newCapacity=hugeCapacity(minCapacity);

//調(diào)用Arrays.copyOf方法將elementData數(shù)組指向新的內(nèi)存空間時newCapacity的連續(xù)空間

//并將elementData的數(shù)據(jù)復制到新的內(nèi)存空間

elementData=Arrays.copyOf(elementData,newCapacity);

}

16.add(Ee)

說明:添加元素e

源碼解釋:

publicbooleanadd(Ee){

//擴容

ensureCapacityInternal(size+1);

//將e賦值給elementData的size+1的位置。

elementData[size++]=e;

returntrue;

}

17.add(intindex,Eelement)

說明:在ArrayList的index位置,添加元素element

源碼解釋:

publicvoidadd(intindex,Eelement){

//判斷index是否越界

rangeCheckForAdd(index);

//擴容

ensureCapacityInternal(size+1);

//將elementData從index位置開始,復制到elementData的index+1開始的連續(xù)空間

System.arraycopy(elementData,index,elementData,index+1,

size-index);

//在elementData的index位置賦值element

elementData[index]=element;

//ArrayList的大小加一

size++;

}

18.remove(intindex)

說明:在ArrayList的移除index位置的元素

源碼解釋:

publicEremove(intindex){

//判斷是否越界

rangeCheck(index);

modCount++;

//讀取舊值

EoldValue=elementData(index);

//獲取index位置開始到最后一個位置的個數(shù)

intnumMoved=size-index-1;

if(numMoved>0)

//將elementData數(shù)組index+1位置開始拷貝到elementData從index開始的空間

System.arraycopy(elementData,index+1,elementData,index,

numMoved);

//使size-1,設置elementData的size位置為空,讓GC來清理內(nèi)存空間

elementData[--size]=null;//cleartoletGCdoitswork

returnoldValue;

}

19.remove(Objecto)

說明:在ArrayList的移除對象為O的元素,跟indexOf方法思想基本一致

源碼解釋:

publicbooleanremove(Objecto){

if(o==null){

for(intindex=0;index<size;index++)

if(elementData[index]==null){

fastRemove(index);

returntrue;

}

}else{

for(intindex=0;index<size;index++)

if(o.equals(elementData[index])){

fastRemove(index);

returntrue;

}

}

returnfalse;

}

20.clear()

說明:設置全部元素為null值,并設置size為0。

源碼解釋:可見clear操作并不是從空間內(nèi)刪除,只是設置為null值,等待垃圾回收機制來回收而已,把size設置為0,以便我們不會瀏覽到null值的內(nèi)存空間。

publicvoidclear(){

modCount++;

//cleartoletGCdoitswork

for(inti=0;i<size;i++)

elementData[i]=null;

size=0;

}

21.addAll(Collectionc)

說明:將Collectionc的全部元素添加到ArrayList中

源碼解釋:

publicbooleanaddAll(Collectionc){

//將c轉換為數(shù)組a

Object[]a=c.toArray();

//獲取a占的內(nèi)存空間長度賦值給numNew

intnumNew=a.length;

//擴容至size+numNew

ensureCapacityInternal(size+numNew);//IncrementsmodCount

//將a的第0位開始拷貝至elementData的size位開始,拷貝長度為numNew

System.arraycopy(a,0,elementData,size,numNew);

//將size增加numNew

size+=numNew;

//如果c為空,返回false,c不為空,返回true

returnnumNew!=0;

}

22.addAll(intindex,Collectionc)

說明:從第index位開始,將c全部拷貝到ArrayList

源碼解釋:

publicbooleanaddAll(intindex,Collectionc){

//判斷index大于size或者是小于0,如果是,則拋出IndexOutOfBoundsException異常

rangeCheckForAdd(index);

//將c轉換為數(shù)組a

Object[]a=c.toArray();

intnumNew=a.length;

//擴容至size+numNew

ensureCapacityInternal(size+numNew);//IncrementsmodCount

//獲取需要添加的個數(shù)

intnumMoved=size-index;

if(numMoved>0)

System.arraycopy(elementData,index,elementData,index+numNew,

numMoved);

System.arraycopy(a,0,elementData,index,numNew);

size+=numNew;

returnnumNew!=0;

}

24.batchRemove(Collectionc,booleancomplement)

說明:根據(jù)complement值,將ArrayList中包含c中元素的元素刪除或者保留

源碼解釋:

privatebooleanbatchRemove(Collectionc,booleancomplement){

finalObject[]elementData=this.elementData;

//定義一個w,一個r,兩個同時右移

intr=0,w=0;

booleanmodified=false;

try{

//r先右移

for(;r<size;r++)

//如果c中不包含elementData[r]這個元素

if(c.contains(elementData[r])==complement)

//則直接將r位置的元素賦值給w位置的元素,w自增

elementData[w++]=elementData[r];

}finally{

//防止拋出異常導致上面r的右移過程沒完成

if(r!=size){

//將r未右移完成的位置的元素賦值給w右邊位置的元素

System.arraycopy(elementData,r,

elementData,w,

size-r);

//修改w值增加size-r

w+=size-r;

}

if(w!=size){

//如果有被覆蓋掉的元素,則將w后面的元素都賦值為null

for(inti=w;i<size;i++)

elementData[i]=null;

modCount+=size-w;

//修改size為w

size=w;

modified=true;

}

}

returnmodified;

}

25.removeAll(Collectionc)

說明:ArrayList移除c中的所有元素

源碼解釋:

publicbooleanremoveAll(Collectionc){

//如果c為空,則拋出空指針異常

Objects.requireNonNull(c);

//調(diào)用batchRemove移除c中的元素

returnbatchRemove(c,false);

}

26.retainAll(Collectionc)

說明:和removeAll相反,僅保留c中所有的元素

源碼解釋:

publicbooleanretainAll(Collectionc){

Objects.requireNonNull(c);

//調(diào)用batchRemove保留c中的元素

returnbatchRemove(c,true);

}

27.iterator()

說明:返回一個Iterator對象,Itr為ArrayList的一個內(nèi)部類,其實現(xiàn)了Iterator接口

publicIteratoriterator(){

returnnewItr();

}

28.listIterator()

說明:返回一個ListIterator對象,ListItr為ArrayList的一個內(nèi)部類,其實現(xiàn)了ListIterator接口

源碼解釋:

publicListIteratorlistIterator(){

returnnewListItr(0);

}

29.listIterator(intindex)

說明:返回一個從index開始的ListIterator對象

源碼解釋:

publicListIteratorlistIterator(intindex){

if(index<0||index>size)

thrownewIndexOutOfBoundsException("Index:"+index);

returnnewListItr(index);

}

30.subList(intfromIndex,inttoIndex)

說明:根據(jù)兩個參數(shù),獲取到一個子序列

源碼解釋:

publicListsubList(intfromIndex,inttoIndex){

//檢查異常

subListRangeCheck(fromIndex,toIndex,size);

//調(diào)用SubList類的構造方法

returnnewSubList(this,0,fromIndex,toIndex);

}

五、內(nèi)部類

(1)privateclassItrimplementsIterator

(2)privateclassListItrextendsItrimplementsListIterator

(3)privateclassSubListextendsAbstractListimplementsRandomAccess

(4)staticfinalclassArrayListSpliteratorimplementsSpliterator

ArrayList有四個內(nèi)部類,

其中的Itr是實現(xiàn)了Iterator接口,同時重寫了里面的hasNext(),next(),remove()等方法;

其中的ListItr繼承Itr,實現(xiàn)了ListIterator接口,同時重寫了hasPrevious(),nextIndex(),

previousIndex(),previous(),set(Ee),add(Ee)等方法,所以這也可以看出了Iterator和ListIterator的區(qū)別,就是ListIterator在Iterator的基礎上增加了添加對象,修改對象,逆向遍歷等方法,這些是Iterator不能實現(xiàn)的。具體可以參考http://blog.csdn.net/a597926661/article/details/7679765。

其中的SubList繼承AbstractList,實現(xiàn)了RandmAccess接口,類內(nèi)部實現(xiàn)了對子序列的增刪改查等方法,但它同時也充分利用了內(nèi)部類的優(yōu)點,就是共享ArrayList的全局變量,例如檢查器變量modCount,數(shù)組elementData等,所以SubList進行的增刪改查操作都是對ArrayList的數(shù)組進行的,并沒有創(chuàng)建新的數(shù)組。
本文是針對Java1.8的源代碼進行解析的,可能會和其他版本有所出入。

一、繼承和實現(xiàn)

繼承:AbstractList

實現(xiàn):List,RandomAccess,Cloneable,Serializable接口

源代碼

publicclassArrayListextendsAbstractList

implementsList,RandomAccess,Cloneable,java.io.Serializable{

}

二、全局變量

1.默認容量

privatestaticfinalintDEFAULT_CAPACITY=10;

2.空的對象數(shù)組

privatestaticfinalObject[]EMPTY_ELEMENTDATA={};

3.默認的空數(shù)組

//無參構造函數(shù)創(chuàng)建的數(shù)組

privatestaticfinalObject[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA={};

4.存放數(shù)據(jù)的數(shù)組的緩存變量,不可序列化

transientObject[]elementData;

5.數(shù)組的大小

privateintsize;

三、構造方法

1.帶有容量initialCapacity的構造方法

源碼解釋:

publicArrayList(intinitialCapacity){

//如果初始化時ArrayList大小大于0

if(initialCapacity>0){

//new一個該大小的object數(shù)組賦給elementData

this.elementData=newObject[initialCapacity];

}elseif(initialCapacity==0){//如果大小為0

//將空數(shù)組賦給elementData

this.elementData=EMPTY_ELEMENTDATA;

}else{//小于0

//則拋出IllegalArgumentException異常

thrownewIllegalArgumentException("IllegalCapacity:"+

initialCapacity);

}

}

2.不帶參數(shù)的構造方法

源碼解釋:

publicArrayList(){

//直接將空數(shù)組賦給elementData

this.elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}

3.帶參數(shù)Collection的構造方法

源碼解釋:

參數(shù)c為一個Collection,Collection的實現(xiàn)類大概有以下幾種常用類型:

List:元素可以重復的容器

Set:元素不可重復的容器

Queue:結構是一個隊列,先進先出

這個構造方法的意思是,將一個Collection實現(xiàn)類的對象轉換為一個ArrayList,但是c容器裝的內(nèi)容

必須為ArrayList裝的內(nèi)容的子類。例如,將一個裝了String內(nèi)容的HashSet轉換為裝了String內(nèi)容的

ArrayList,使得ArrayList的大小和值數(shù)組都是HashSet的大小和值數(shù)組。具體實現(xiàn)如下代碼,首先調(diào)

用c(Collection的具體實現(xiàn)類)的toArray方法,具體大家可以看各個實現(xiàn)類的toArray方法,但是大

概意思都是將c容器轉換為object類型的數(shù)組,因為它們的返回值都是object[]。之于下面的兩個判斷

是當?shù)玫降膃lementData的類名不是Object類名的時候或者是長度為0的時候才會執(zhí)行。

publicArrayList(Collectionc){

elementData=c.toArray();

if((size=elementData.length)!=0){

if(elementData.getClass()!=Object[].class)

elementData=Arrays.copyOf(elementData,size,Object[].class);

}else{

//replacewithemptyarray.

this.elementData=EMPTY_ELEMENTDATA;

}

}

四、方法

1.trimToSize()

說明:將ArrayList的容量設置為當前size的大小。首先需要明確一個概念,ArrayList的size就是ArrayList的元素個數(shù),length是ArrayList申請的內(nèi)容空間長度。ArrayList每次都會預申請多一點空間,以便添加元素的時候不需要每次都進行擴容操作,例如我們的元素個數(shù)是10個,它申請的內(nèi)存空間必定會大于10,即length>size,而這個方法就是把ArrayList的內(nèi)存空間設置為size,去除沒有用到的null值空間。這也就是我們?yōu)槭裁疵看卧讷@取數(shù)據(jù)長度是都是調(diào)用list.size()而不是list.length()。

源碼解釋:首先modCount是從類java.util.AbstractList繼承的字段,這個字段主要是為了防止在多線程操作的情況下,List發(fā)生結構性的變化,什么意思呢?就是防止一個線程正在迭代,另外一個線程進行對List進行remove操作,這樣當我們迭代到最后一個元素時,很明顯此時List的最后一個元素為空,那么這時modCount就會告訴迭代器,讓其拋出異常ConcurrentModificationException。

如果沒有這一個變量,那么系統(tǒng)肯定會報異常ArrayIndexOutOfBoundsException,這樣的異常顯然不是應該出現(xiàn)的(這些運行時錯誤都是使用者的邏輯錯誤導致的,我們的JDK那么高端,不會出現(xiàn)使用錯誤,我們只拋出使用者造成的錯誤,而這個錯誤是設計者應該考慮的),為了避免出現(xiàn)這樣的異常,定義了檢查。

(引用自:郭無心,詳情可以看他在知乎的回答:https://www.zhihu.com/question/24086463/answer/64717159)。

publicvoidtrimToSize(){

modCount++;

//如果size小于length

if(size<elementData.length){

//重新將elementData設置大小為size

elementData=(size==0)

?EMPTY_ELEMENTDATA

:Arrays.copyOf(elementData,size);

}

}

2.size()

說明:返回ArrayList的大小

源碼解釋:直接返回size

publicintsize(){

returnsize;

}

3.isEmpty()

說明:返回是否為空

**源碼解釋:**直接返回判斷size==0

publicbooleanisEmpty(){

returnsize==0;

}

4.indexOf(Objecto)

說明:對象o在ArrayList中的下標位置,如果存在返回位置i,不存在返回-1

源碼解釋:遍歷ArrayList的大小,比較o和容器內(nèi)的元素,若相等,則返回位置i,若遍歷完都不相等,返回-1

publicintindexOf(Objecto){

if(o==null){

for(inti=0;i<size;i++)

if(elementData[i]==null)

returni;

}else{

for(inti=0;i<size;i++)

if(o.equals(elementData[i]))

returni;

}

return-1;

}

5.contains(Objecto)

說明:是否包含對象o

源碼解釋:調(diào)用indexOf()方法得到下標,存在則下標>=0,不存在為-1,即只要比較下標和0的大小即可。

publicbooleancontains(Objecto){

returnindexOf(o)>=0;

}

6.lastIndexOf(Objecto)

說明:返回容器內(nèi)出現(xiàn)o的最后一個位置

源碼解釋:從后向前遍歷,得到第一個出現(xiàn)對象o的位置,不存在則返回-1

publicintlastIndexOf(Objecto){

if(o==null){

for(inti=size-1;i>=0;i--)

if(elementData[i]==null)

returni;

}else{

for(inti=size-1;i>=0;i--)

if(o.equals(elementData[i]))

returni;

}

return-1;

}

7.clone()

說明:返回此ArrayList實例的淺表副本。

源碼解釋:

publicObjectclone(){

try{

//調(diào)用父類(翻看源碼可見是Object類)的clone方法得到一個ArrayList副本

ArrayListv=(ArrayList)super.clone();

//調(diào)用Arrays類的copyOf,將ArrayList的elementData數(shù)組賦值給副本的elementData數(shù)組

v.elementData=Arrays.copyOf(elementData,size);

v.modCount=0;

//返回副本v

returnv;

}catch(CloneNotSupportedExceptione){

thrownewInternalError(e);

}

}

8.toArray()

說明:ArrayList實例轉換為。

源碼解釋:直接調(diào)用Arrays類的copyOf。

publicObject[]toArray(){

returnArrays.copyOf(elementData,size);

}

9.toArray(T[]a)

說明:將ArrayList里面的元素賦值到一個數(shù)組中去

源碼解釋:如果a的長度小于ArrayList的長度,直接調(diào)用Arrays類的copyOf,返回一個比a數(shù)組長度要大的新數(shù)組,里面元素就是ArrayList里面的元素;如果a的長度比ArrayList的長度大,那么就調(diào)用System.arraycopy,將ArrayList的elementData數(shù)組賦值到a數(shù)組,然后把a數(shù)組的size位置賦值為空。

publicT[]toArray(T[]a){

if(a.length<size)

//Makeanewarrayofa'sruntimetype,butmycontents:

return(T[])Arrays.copyOf(elementData,size,a.getClass());

System.arraycopy(elementData,0,a,0,size);

if(a.length>size)

a[size]=null;

returna;

}

10.rangeCheck(intindex)

說明:測試index是否越界

源碼解釋:

privatevoidrangeCheck(intindex){

//如果下標超過ArrayList的數(shù)組長度

if(index>=size)

//拋出IndexOutOfBoundsException異常

thrownewIndexOutOfBoundsException(outOfBoundsMsg(index));

}

11.get(intindex)

說明:獲取index位置的元素

源碼解釋:先檢查是否越界,然后返回ArrayList的elementData數(shù)組index位置的元素。

publicEget(intindex){

//檢查是否越界

rangeCheck(index);

//返回ArrayList的elementData數(shù)組index位置的元素

returnelementData(index);

}

12.set(intindex,Eelement)

說明:設置index位置的元素值了element,返回該位置的之前的值

源碼解釋:

publicEset(intindex,Eelement){

//檢查是否越界

rangeCheck(index);

//調(diào)用elementData(index)獲取到當前位置的值

EoldValue=elementData(index);

//將element賦值到ArrayList的elementData數(shù)組的第index位置

elementData[index]=element;

returnoldValue;

}

13.ensureCapacityInternal(intminCapacity)

說明:得到最小擴容量

源碼解釋:

privatevoidensureCapacityInternal(intminCapacity){

if(elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA){

//獲取默認的容量和傳入?yún)?shù)的較大值

minCapacity=Math.max(DEFAULT_CAPACITY,minCapacity);

}

ensureExplicitCapacity(minCapacity);

}

14.ensureExplicitCapacity(intminCapacity)

說明:判斷是否需要擴容

源碼解釋:

privatevoidensureExplicitCapacity(intminCapacity){

modCount++;

//如果最小需要空間比elementData的內(nèi)存空間要大,則需要擴容

if(minCapacity-elementData.length>0)

grow(minCapacity);

}

15.grow()方法

說明:幫助ArrayList動態(tài)擴容的核心方法

源碼解釋:

//MAX_VALUE為231-1,MAX_ARRAY_SIZE就是獲取Java中int的最大限制,以防止越界

privatestaticfinalintMAX_ARRAY_SIZE=Integer.MAX_VALUE-8;

privatevoidgrow(intminCapacity){

//獲取到ArrayList中elementData數(shù)組的內(nèi)存空間長度

intoldCapacity=elementData.length;

//擴容至原來的1.5倍

intnewCapacity=oldCapacity+(oldCapacity>>1);

//再判斷一下新數(shù)組的容量夠不夠,夠了就直接使用這個長度創(chuàng)建新數(shù)組,

//不夠就將數(shù)組長度設置為需要的長度

if(newCapacity-minCapacity<0)

newCapacity=minCapacity;

//判斷有沒超過最大限制

if(newCapacity-MAX_ARRAY_SIZE>0)

newCapacity=hugeCapacity(minCapacity);

//調(diào)用Arrays.copyOf方法將elementData數(shù)組指向新的內(nèi)存空間時newCapacity的連續(xù)空間

//并將elementData的數(shù)據(jù)復制到新的內(nèi)存空間

elementData=Arrays.copyOf(elementData,newCapacity);

}

16.add(Ee)

說明:添加元素e

源碼解釋:

publicbooleanadd(Ee){

//擴容

ensureCapacityInternal(size+1);

//將e賦值給elementData的size+1的位置。

elementData[size++]=e;

returntrue;

}

17.add(intindex,Eelement)

說明:在ArrayList的index位置,添加元素element

源碼解釋:

publicvoidadd(intindex,Eelement){

//判斷index是否越界

rangeCheckForAdd(index);

//擴容

ensureCapacityInternal(size+1);

//將elementData從index位置開始,復制到elementData的index+1開始的連續(xù)空間

System.arraycopy(elementData,index,elementData,index+1,

size-index);

//在elementData的index位置賦值element

elementData[index]=element;

//ArrayList的大小加一

size++;

}

18.remove(intindex)

說明:在ArrayList的移除index位置的元素

源碼解釋:

publicEremove(intindex){

//判斷是否越界

rangeCheck(index);

modCount++;

//讀取舊值

EoldValue=elementData(index);

//獲取index位置開始到最后一個位置的個數(shù)

intnumMoved=size-index-1;

if(numMoved>0)

//將elementData數(shù)組index+1位置開始拷貝到elementData從index開始的空間

System.arraycopy(elementData,index+1,elementData,index,

numMoved);

//使size-1,設置elementData的size位置為空,讓GC來清理內(nèi)存空間

elementData[--size]=null;//cleartoletGCdoitswork

returnoldValue;

}

19.remove(Objecto)

說明:在ArrayList的移除對象為O的元素,跟indexOf方法思想基本一致

源碼解釋:

publicbooleanremove(Objecto){

if(o==null){

for(intindex=0;index<size;index++)

if(elementData[index]==null){

fastRemove(index);

returntrue;

}

}else{

for(intindex=0;index<size;index++)

if(o.equals(elementData[index])){

fastRemove(index);

returntrue;

}

}

returnfalse;

}

20.clear()

說明:設置全部元素為null值,并設置size為0。

源碼解釋:可見clear操作并不是從空間內(nèi)刪除,只是設置為null值,等待垃圾回收機制來回收而已,把size設置為0,以便我們不會瀏覽到null值的內(nèi)存空間。

publicvoidclear(){

modCount++;

//cleartoletGCdoitswork

for(inti=0;i<size;i++)

elementData[i]=null;

size=0;

}

21.addAll(Collectionc)

說明:將Collectionc的全部元素添加到ArrayList中

源碼解釋:

publicbooleanaddAll(Collectionc){

//將c轉換為數(shù)組a

Object[]a=c.toArray();

//獲取a占的內(nèi)存空間長度賦值給numNew

intnumNew=a.length;

//擴容至size+numNew

ensureCapacityInternal(size+numNew);//IncrementsmodCount

//將a的第0位開始拷貝至elementData的size位開始,拷貝長度為numNew

System.arraycopy(a,0,elementData,size,numNew);

//將size增加numNew

size+=numNew;

//如果c為空,返回false,c不為空,返回true

returnnumNew!=0;

}

22.addAll(intindex,Collectionc)

說明:從第index位開始,將c全部拷貝到ArrayList

源碼解釋:

publicbooleanaddAll(intindex,Collectionc){

//判斷index大于size或者是小于0,如果是,則拋出IndexOutOfBoundsException異常

rangeCheckForAdd(index);

//將c轉換為數(shù)組a

Object[]a=c.toArray();

intnumNew=a.length;

//擴容至size+numNew

ensureCapacityInternal(size+numNew);//IncrementsmodCount

//獲取需要添加的個數(shù)

intnumMoved=size-index;

if(numMoved>0)

System.arraycopy(elementData,index,elementData,index+numNew,

numMoved);

System.arraycopy(a,0,elementData,index,numNew);

size+=numNew;

returnnumNew!=0;

}

24.batchRemove(Collectionc,booleancomplement)

說明:根據(jù)complement值,將ArrayList中包含c中元素的元素刪除或者保留

源碼解釋:

privatebooleanbatchRemove(Collectionc,booleancomplement){

finalObject[]elementData=this.elementData;

//定義一個w,一個r,兩個同時右移

intr=0,w=0;

booleanmodified=false;

try{

//r先右移

for(;r<size;r++)

//如果c中不包含elementData[r]這個元素

if(c.contains(elementData[r])==complement)

//則直接將r位置的元素賦值給w位置的元素,w自增

elementData[w++]=elementData[r];

}finally{

//防止拋出異常導致上面r的右移過程沒完成

if(r!=size){

//將r未右移完成的位置的元素賦值給w右邊位置的元素

System.arraycopy(elementData,r,

elementData,w,

size-r);

//修改w值增加size-r

w+=size-r;

}

if(w!=size){

//如果有被覆蓋掉的元素,則將w后面的元素都賦值為null

for(inti=w;i<size;i++)

elementData[i]=null;

modCount+=size-w;

//修改size為w

size=w;

modified=true;

}

}

returnmodified;

}

25.removeAll(Collectionc)

說明:ArrayList移除c中的所有元素

源碼解釋:

publicbooleanremoveAll(Collectionc){

//如果c為空,則拋出空指針異常

Objects.requireNonNull(c);

//調(diào)用batchRemove移除c中的元素

returnbatchRemove(c,false);

}

26.retainAll(Collectionc)

說明:和removeAll相反,僅保留c中所有的元素

源碼解釋:

publicbooleanretainAll(Collectionc){

Objects.requireNonNull(c);

//調(diào)用batchRemove保留c中的元素

returnbatchRemove(c,true);

}

27.iterator()

說明:返回一個Iterator對象,Itr為ArrayList的一個內(nèi)部類,其實現(xiàn)了Iterator接口

publicIteratoriterator(){

returnnewItr();

}

28.listIterator()

說明:返回一個ListIterator對象,ListItr為ArrayList的一個內(nèi)部類,其實現(xiàn)了ListIterator接口

源碼解釋:

publicListIteratorlistIterator(){

returnnewListItr(0);

}

29.listIterator(intindex)

說明:返回一個從index開始的ListIterator對象

源碼解釋:

publicListIteratorlistIterator(intindex){

if(index<0||index>size)

thrownewIndexOutOfBoundsException("Index:"+index);

returnnewListItr(index);

}

30.subList(intfromIndex,inttoIndex)

說明:根據(jù)兩個參數(shù),獲取到一個子序列

源碼解釋:

publicListsubList(intfromIndex,inttoIndex){

//檢查異常

subListRangeCheck(fromIndex,toIndex,size);

//調(diào)用SubList類的構造方法

returnnewSubList(this,0,fromIndex,toIndex);

}

五、內(nèi)部類

(1)privateclassItrimplementsIterator

(2)privateclassListItrextendsItrimplementsListIterator

(3)privateclassSubListextendsAbstractListimplementsRandomAccess

(4)staticfinalclassArrayListSpliteratorimplementsSpliterator

ArrayList有四個內(nèi)部類,

其中的Itr是實現(xiàn)了Iterator接口,同時重寫了里面的hasNext(),next(),remove()等方法;

其中的ListItr繼承Itr,實現(xiàn)了ListIterator接口,同時重寫了hasPrevious(),nextIndex(),

previousIndex(),previous(),set(Ee),add(Ee)等方法,所以這也可以看出了Iterator和ListIterator的區(qū)別,就是ListIterator在Iterator的基礎上增加了添加對象,修改對象,逆向遍歷等方法,這些是Iterator不能實現(xiàn)的。具體可以參考http://blog.csdn.net/a597926661/article/details/7679765。

其中的SubList繼承AbstractList,實現(xiàn)了RandmAccess接口,類內(nèi)部實現(xiàn)了對子序列的增刪改查等方法,但它同時也充分利用了內(nèi)部類的優(yōu)點,就是共享ArrayList的全局變量,例如檢查器變量modCount,數(shù)組elementData等,所以SubList進行的增刪改查操作都是對ArrayList的數(shù)組進行的,并沒有創(chuàng)建新的數(shù)組。


以上就是關于Java培訓之容器類ArrayList源碼分析的詳細介紹,最后想要了解更多關于JavaEE開發(fā)問題的小伙伴可以登錄扣丁學堂官網(wǎng)咨詢??鄱W堂是專業(yè)的JavaEE培訓機構,不僅有專業(yè)的老師和與時俱進的課程體系,還有大量的Java視頻教程供學員觀看學習,想要學好JavaEE的小伙伴抓緊時間行動吧。Java技術交流群:670348138。


關注微信公眾號獲取更多學習資料



關注微信公眾號獲取更多學習資料



查看更多關于“Java開發(fā)資訊的相關文章>>

標簽: Java培訓 Java開發(fā)程序員 Java視頻教程

熱門專區(qū)

暫無熱門資訊

課程推薦

微信
微博
15311698296

全國免費咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權所有   北京市海淀區(qū)寶盛北里西區(qū)28號中關村智誠科創(chuàng)大廈4層
京ICP備2021002079號-2   Copyright ? 2017 - 2022
返回頂部 返回頂部