Java集合之ArrayList擴容機制

2021-09-18 06:17:36 字數 3951 閱讀 9214

//預設初始容量大小(預設能新增10條資料)

private static final int default_capacity = 10;

//預設例項化乙個空陣列

private static final object defaultcapacity_empty_elementdata = {};

//預設建構函式,使用初始容量為10構造乙個空列表(無引數構造)

public arraylist()

//帶初始容量引數的建構函式。(使用者自己指定容量)

public arraylist(int initialcapacity) else if (initialcapacity == 0) else

}

//構造包含指定collection元素的列表,這些元素利用該集合的迭代器按照順序返回,如果指定的集合為空,則丟擲nullpointerexception

public arraylist(collection extends e> c) else

}

以無引數構造方式建立arraylist時,實際上初始化賦值的是乙個空陣列(public arraylist())。當真正對陣列進行新增元素操作時,才真正分配容量。即向陣列中新增第乙個元素時,陣列容量擴為10

/**

*將指定的元素追加到此列表的末尾

*/public boolean add(e e)

//得到最小擴容量

private void ensurecapacityinternal(int mincapacity)

ensureexplicitcapacity(mincapacity);

}

當要add進第乙個元素時,mincapacity為1,在math.max()方法比較後,mincapacity為10

//判斷是否需要擴容

private void ensureexplicitcapacity(int mincapacity)

我們來仔細分析一下當我們要add進第乙個元素到arraylist時,elementdata.length為0(因為還是乙個空的list,裡面還沒有資料,所以沒有進行擴容,預設擴容10),因為執行了ensurecapacityinternal()方法,所以mincapacity此時為10。此時,mincapacity - elemetdata.length > 0(mincapacity=10,elemetdata.length=0)成立,所以會進入==grow(mincapacity)==方法。

當add第2個元素時,mincapacity為2,此時elementdata.length(容量)在新增第乙個元素後擴容成10了。此時,mincapacity - elementdata.length > 0不成立,所以不會進入(執行)==grow(mincapacity)==方法。

新增第3、4…到第10個元素時,依然不會執行==grow()==方法,陣列容量都為10。

知道新增第11個元素,mincapacity(為11)比elementdata.length(為10)要大。進行grow方法進行擴容grow方法

private void grow(int mincapacity)
int newcapacity = oldcapacity + (oldcapacity >> 1),所以 arraylist 每次擴容之後容量都會變為原來的 1.5 倍!

「>>」(移位運算子):>>1 右移一位相當於除2,右移n位相當於除以 2 的 n 次方。這裡 oldcapacity 明顯右移了1位所以相當於oldcapacity /2。對於大資料的2進製運算,位移運算子比那些普通運算子的運算要快很多,因為程式僅僅移動一下而已,不去計算,這樣提高了效率,節省了資源

通過例子**一下grow()方法

// 將指定的元素插入此列表中的指定位置。  

// 如果當前位置有元素,則向右移動當前位於該位置的元素以及所有後續元素(將其索引加1)。

public void add(int index, e element)

public static void main(string args)

看到插入的時候,按照指定位置,把從指定位置開始的所有元素利用system.arraycopy方法做乙個整體的複製,向後移動乙個位置(當然先要用ensurecapacity方法進行判斷,加了乙個元素之後陣列會不會不夠大),然後指定位置的元素設定為需要插入的元素,完成了一次插入的操作。用圖表示這個過程是這樣的

``在這個方法中最根本的方法就是system.arraycopy()方法,該方法的根本目的就是將index位置空出來以供新資料插入,這裡需要進行陣列資料的右移,這是非常麻煩和耗時的,所以如果指定的資料集合需要進行大量插入(中間插入)操作,推薦使用linkedlist。

1、把指定元素後面位置的所有元素,利用system.arraycopy方法整體向前移動乙個位置

2、最後乙個位置的元素指定為null,這樣讓gc可以去**它

inta = new int[10];

a[0] =0;

a[1] =1;

a[2] =2;

a[3] =3;

a[4]=4;

a[5]=5;

a[6]=6;

a[7]=7;

a[8]=8;

a[9]=9;

system.arraycopy(a,2,a,3,7);

for (int i=0;i從原陣列(a)中第2位開始往後面取三位(2.3.4),然後copy到新陣列(這裡還是a)中,從第3位開始放(3.4.5被替換成原陣列的2.3.4)

2019-04-15 17:50:27.658 28361-28361/? i/system.out: 0****0

2019-04-15 17:50:27.658 28361-28361/? i/system.out: 1****1

2019-04-15 17:50:27.658 28361-28361/? i/system.out: 2****2

2019-04-15 17:50:27.658 28361-28361/? i/system.out: 3****2

2019-04-15 17:50:27.658 28361-28361/? i/system.out: 4****3

2019-04-15 17:50:27.658 28361-28361/? i/system.out: 5****4

2019-04-15 17:50:27.658 28361-28361/? i/system.out: 6****5

2019-04-15 17:50:27.658 28361-28361/? i/system.out: 7****6

2019-04-15 17:50:27.658 28361-28361/? i/system.out: 8****7

2019-04-15 17:50:27.658 28361-28361/? i/system.out: 9****8

Java中Vector和ArrayList的區別

首先看這兩類都實現list介面,而list介面一共有三個實現類,分別是arraylist vector和linkedlist。list用於存放多個元素,能夠維護元素的次序,並且允許元素的重複。3個具體實現類的相關區別如下 arraylist是最常用的list實現類,內部是通過陣列實現的,它允許對元素...

Java中Vector和ArrayList的區別

首先看這兩類都實現list介面,而list介面一共有三個實現類,分別是arraylist vector和linkedlist。list用於存放多個元素,能夠維護元素的次序,並且允許元素的重複。3個具體實現類的相關區別如下 arraylist是最常用的list實現類,內部是通過陣列實現的,它允許對元素...

Java中Vector和ArrayList的區別

首先看這兩類都實現list介面,而list介面一共有三個實現類,分別是arraylist vector和linkedlist。list用於存放多個元素,能夠維護元素的次序,並且允許元素的重複。3個具體實現類的相關區別如下 1 arraylist是最常用的list實現類,內部是通過陣列實現的,它允許對...