Arraylist動態擴容詳解

2021-08-16 16:16:12 字數 3216 閱讀 9918

arraylist是基於陣列實現的,是乙個動態陣列,其容量能自動增長。

arraylist不是執行緒安全的,只能用在單執行緒環境下。

實現了serializable介面,因此它支援序列化,能夠通過序列化傳輸;

實現了randomaccess介面,支援快速隨機訪問,實際上就是通過下標序號進行快速訪問;

實現了cloneable介面,能被轉殖。

一 初始化首先有三種方式來初始化:

public arraylist();
預設的構造器,將會以預設的大小來初始化內部的陣列

public arraylist(collection extends e> c)
用乙個icollection物件來構造,並將該集合的元素新增到arraylist

public arraylist(int initialcapacity)
用指定的大小來初始化內部的陣列

後兩種方式都可以理解,通過創造物件,或指定大小來初始化內部資料即可。 

那我們來重點關注一下無引數構造器的實現過程:

/**

* constructs an empty list with an initial capacity of ten.

*/public

arraylist()

private

static

final object defaultcapacity_empty_elementdata = {};

可以看出它的預設陣列為長度為0。而在之前jdk1,6中,無引數構造器**是初始長度為10。 

jdk6**這樣的:

public

arraylist()

public arraylist(int

initialcapacity)

接下來,要擴容的話,肯定是在arraylist.add 方法中。我們來看一下具體實現。

二  確保內部容量

我們以無引數構造為例, 

初始化時,陣列長度為0. 

那我現在要新增資料了,陣列的長度是怎麼變化的?

public

boolean

add(e e)

① ensurecapacityinternal方法名的英文大致是「確保內部容量」,size表示的是執行新增之前的元素個數,並非arraylist的容量,容量應該是陣列elementdata的長度。ensurecapacityinternal該方法通過將現有的元素個數陣列的容量比較。看如果需要擴容,則擴容。 

②是將要新增的元素放置到相應的陣列中。 

下面具體看ensurecapacityinternal(size + 1);

// ① 是如何判斷和擴容的。

private

void ensurecapacityinternal(int

mincapacity)

ensureexplicitcapacity(mincapacity);

}private

void ensureexplicitcapacity(int

mincapacity)

/*** default initial capacity.

*/private

static

final

int default_capacity = 10;

以上,elementdata是用來儲存實際內容的陣列。minexpand 是最小擴充容量。 

defaultcapacity_empty_elementdata共享的空陣列例項用於預設大小的空例項。根據傳入的最小需要容量mincapacity來和陣列的容量長度對比,若mincapactity大於或等於陣列容量,則需要進行擴容。

三 擴容

/*

*增加容量,以確保它至少能容納

*由最小容量引數指定的元素數。

* @param mincapacity所需的最小容量

*/private

void grow(int

mincapacity)

綜上所述arraylist相當於在沒指定initialcapacity時就是會使用延遲分配物件陣列空間,當第一次插入元素時才分配10(預設)個物件空間。假如有20個資料需要新增,那麼會分別在第一次的時候,將arraylist的容量變為10 (如下圖一);之後擴容會按照1.5倍增長。也就是當新增第11個資料的時候,arraylist繼續擴容變為10*1.5=15(如下圖二);當新增第16個資料時,繼續擴容變為15 * 1.5 =22個(如下圖四)。:

向陣列中新增第乙個元素時,陣列容量為10.

向陣列中新增到第10個元素時,陣列容量仍為10.

向陣列中新增到第11個元素時,陣列容量擴為15.

向陣列中新增到第16個元素時,陣列容量擴為22.

每次擴容都是通過arrays.copyof(elementdata, newcapacity) 這樣的方式實現的。

本文介紹了arraylist動態擴容的全過程。如果通過無參構造的話,初始陣列容量為0,當真正對陣列進行新增時,才真正分配容量。每次按照1.5倍(位運算)的比率通過copeof的方式擴容。 在jkd1.6中實現是,如果通過無參構造的話,初始陣列容量為10,每次通過copeof的方式擴容後容量為原來的1.5倍,以上就是動態擴容的原理。

ArrayList動態擴容機制

初始化 有三種方式預設的構造器,將會以預設的大小來初始化內部的陣列 public arraylist 用乙個icollection物件來構造,並將該集合的元素新增到arraylist public arraylist collection c 用指定的大小來初始化內部的陣列 public array...

ArrayList的動態擴容

arraylist可以實現容量的自適應的增加,通過閱讀源 對這個機制進行一下簡單的分析。首先,arraylist有乙個初始的預設大小,為10.private static final int default capacity 10 從add方法為入口 public boolean add e e 可...

ArrayList的動態擴容機制

一般問的時候應該是用jdk1.6回答 jdk1.7之後也要知道 初始化 有三種方式預設的構造器,將會以預設的大小來初始化內部的陣列 public arraylist 用乙個icollection物件來構造,並將該集合的元素新增到arraylist public arraylist collectio...