適AT Arraylist動態擴容詳解

2021-07-31 18:11:12 字數 2839 閱讀 6661

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倍,以上就是動態擴容的原理。

為動態陣列擴容

問題及 檔名稱 test.cpp 作 者 李尚澤 完成日期 2014年12月16日 版 本 號 v1.0 問題描述 利用動態陣列儲存學生的成績,當再有一批學生成績需要儲存時,要為之擴容。includeusing namespace std int main int num,i,addnum num是...

vmware磁碟動態擴容

今天,任務為 172.16.1.82 磁碟擴容 echo sys class scsi host host0 scan sys class scsi host 下面有幾個 host 就掃瞄幾次 今天,任務完成 172.16.1.82 磁碟擴容後繼工作 當前僅對沒有在持久模式下開啟快照的 vmfs 平...

ArrayList動態擴容機制

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