ArrayList原始碼分析及高頻面試問題答案

2021-10-05 15:35:51 字數 3033 閱讀 1203

transient object[

] elementdata; //陣列容量

private int size; //實際存的元素個數

下文將會頻繁提及它們。

構造方法1:

public arraylist(int initialcapacity)

else

if(initialcapacity == 0)

else

}

傳入初始值,則直接生成乙個相應長度object陣列,此時size值是多少呢?

由於沒有賦值,則仍舊使用例項化時的值,即0。

構造方法2:

private static final object[

] defaultcapacity_empty_elementdata =;..

....

public arraylist(

)

將elementdata賦值為乙個空的object陣列,此時size=0;

構造方法3:

public arraylist(collection<? extends e> c)

else

}

傳入引數為乙個集合物件,首先將集合轉化為陣列,然後使用系統函式將該陣列copy到elementdata,即完成了賦值。此時size=elementdata.length 即集合物件的長度。

下面看下add方法:

private static final int default_capacity = 10;

private static final object[

] defaultcapacity_empty_elementdata =

;public boolean add(e e)

private void ensurecapacityinternal(int mincapacity)

private void ensureexplicitcapacity(int mincapacity)

private static int calculatecapacity(object[

] elementdata, int mincapacity)

return mincapacity;

}

增加乙個元素,首先確保容量正確。

將當前的size+1傳給calculatecapacity方法,如果陣列中不存在元素,取size+1與10相比的最大值,返回。否則直接返回size+1。

然後size+1的值傳入ensureexplicitcapacity 方法。如果該值大於實際目前陣列中元素個數,說明當前空間不夠了,需要擴容。否則除了增加modcount值後,不進行更多操作。modcount的作用我們稍後再說。

我們看下grow方法

private static final int max_array_size = integer.max_value - 8;

private void grow(int mincapacity)

private static int hugecapacity(int mincapacity)

首先對現有容量增加50%,去其與所需容量的最大值,如果該值大於integer.max_value - 8,則返回integer.max_value。所以一般所需容量小於現有容量的1.5倍,則使用1.5倍值,否則使用所需容量值,來新建陣列並將舊資料copy過來。

下面看下get 方法:

public e get(int index)

private void rangecheck(int index)

首先進行下標越界檢查,然後通過下標返回該元素。

下面看下set方法:

public e set(int index, e element)

可以看到是將index對應的值修改後,返回舊值。

remove方法

public e remove(int index)

可以看到是使用了 system.arraycopy將index後面的元素都copy往前移一位,將舊值返回。

可見刪除元素代價較大,而且元素越靠前,所要移動的資料就越多。

在指定位置新增元素add(int index, e element)

public void add(int index, e element)

可見是通過system.arraycopy,將資料進行copy,代價較高。

總結如下,例項化:用無參方法初始化時,只分配了乙個空陣列。使用容量引數初始化時,分配乙個引數大小的陣列。使用集合作為引數初始化時,將集合轉為陣列,copy到新陣列。

擴容機制是什麼?

當陣列元素為0時,第一次新增元素,容量變為10。此後add元素後所需容量大於現有容量時,進行擴容,擴容為1.5倍,如果還不夠,則使用當前元素總數為陣列長度。

arraylist的優缺點是什麼?

優點:可以根據下標快速找到元素(跟linkedlist相比),可以自動擴容(跟陣列相比)。

缺點:1.指定下標增刪資料,需要使用system.arraycopy 本地方法將該下標以後的資料進行大面積copy,效率較低。2.陣列中可能會存在空元素,造成一定的空間浪費。

arraylist使用場景有哪些?

適用於需要根據下標查詢的可變長陣列的情況。避免在需要對元素大量增刪情況下使用(對列尾部增刪無限制)。

以上。

ArrayList原始碼分析

arraylist是平時使用很多的乙個類,趁有時間,我也閱讀以下原始碼,以幫助自己加深理解。類的層次結構這裡就不列出了,主要分析一下原始碼部分,屬性部分 protected transient int modcount 0 這個屬性是從abstractlist繼承過來的,每次arraylist進行結...

ArrayList原始碼分析

有參建構函式傳入乙個int public arraylist int capacity 如果為0則返回空陣列,否則new 乙個capacity的陣列 array capacity 0 emptyarray.object new object capacity 無參建構函式 public arrayl...

ArrayList原始碼分析

最近因為擁抱變換,所以開始無奈的面試之路。因為在集合的原始碼分析上,出了些問題,所以這段時間,好好重新理一理常用的集合原始碼。版本基於jdk1.7 毫無疑問,提到常用集合。arraylist勢必是第乙個被搬出來的,因此我們就先拿它開刀了。arraylist的初始化,只有在第一次add的時候進行new...