簡書:capo
轉(zhuǎn)載請注明原創(chuàng)出處,謝謝充择!
今天,我們分析下JDK8中ArrayList的源碼,我們知道ArrayList是List接口的一個實(shí)現(xiàn),是一個動態(tài)擴(kuò)容的數(shù)組闽晦。那么它是怎樣在我們添加元素時實(shí)現(xiàn)動態(tài)擴(kuò)容的了?
這是數(shù)組定義的幾個成員變量
image.png
首先我們調(diào)用數(shù)組的 add(E e) 方法時,這里我用的是一個重載的方法,第一個參數(shù)指的是要添加元素的下標(biāo),默認(rèn)如果我們不提供這個參數(shù)的話是從數(shù)組的最后添加的。
public void add(int var1, E var2) {
//檢查數(shù)組下標(biāo)
this.rangeCheckForAdd(var1);
//保證數(shù)組內(nèi)部容量 插入數(shù)組位置往后移動一個位置
this.ensureCapacityInternal(this.size + 1);
//舊的數(shù)組就會使用Arrays.copyOf方法被復(fù)制到新的數(shù)組中,現(xiàn)有的數(shù)組指向了新的數(shù)組
System.arraycopy(this.elementData, var1, this.elementData, var1 + 1, this.size - var1);
this.elementData[var1] = var2;
++this.size;
}
Java會檢查這個數(shù)組下標(biāo)是否超過這個數(shù)組的長度或者下標(biāo)小于0,如果是的話就拋出
IndexOutOfBoundsException異常
private void rangeCheckForAdd(int var1) {
if(var1 > this.size || var1 < 0) {
throw new IndexOutOfBoundsException(this.outOfBoundsMsg(var1));
}
}
如果數(shù)組元素等于默認(rèn)空數(shù)組的話,那么數(shù)組插入數(shù)組索引下標(biāo)會進(jìn)行一個取最大值的操作
private void ensureCapacityInternal(int var1) {
//如果添加的這個元素 == 默認(rèn)的空數(shù)組的第一個元素
if(this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
var1 = Math.max(10, var1); //在數(shù)組初始容量和數(shù)組的下標(biāo)中取一個最大值
}
//明確保證數(shù)組的容量
this.ensureExplicitCapacity(var1);
}
為了明確保證數(shù)組容量序列化計(jì)算
private void ensureExplicitCapacity(int var1) {
//反序列化計(jì)算器加 1
++this.modCount;
//如果要指定添加元素的下標(biāo)位置 > 數(shù)組長度 此時就要擴(kuò)容
if(var1 - this.elementData.length > 0) {
this.grow(var1);
}
}
計(jì)算新數(shù)組的長度=原始數(shù)組的1.5倍
private void grow(int var1) {
int var2 = this.elementData.length;
//新的數(shù)組長度 = 原始數(shù)組長度 + 原始數(shù)組 / 2
int var3 = var2 + (var2 >> 1);
//如果新的數(shù)組長度 < 要添加元素的位置
if(var3 - var1 < 0) {
var3 = var1;//新數(shù)組長度 = 添加元素的位置長度
}
//如果新的數(shù)組長度 > 2147483639
if(var3 - 2147483639 > 0) {
var3 = hugeCapacity(var1); //就判斷是否超過了JVM內(nèi)存
}
this.elementData = Arrays.copyOf(this.elementData, var3);
}
判斷這個新數(shù)組長度是否JVM內(nèi)存分配的最大值
private static int hugeCapacity(int var0) {
if(var0 < 0) {
throw new OutOfMemoryError();
} else {
return var0 > 2147483639?2147483647:2147483639;
}
}
總結(jié)一下:
- ArrayList底層是一個動態(tài)擴(kuò)容的數(shù)
- 數(shù)組的初始長度是10個單位
- 如果指定了要添加元素的索引下標(biāo)的話提岔,如果這個數(shù)組元素默認(rèn)初始空數(shù)組的話就取一個最小值(添加元素的下標(biāo)索引)
- 擴(kuò)容后新數(shù)組的長度 = 原始數(shù)組長度 + 原始數(shù)組長度/2 (也就是原始數(shù)組長度的1.5倍)
- 數(shù)組的長度不是沒有上限的,如果超過2147483639就會報(bào)OOM