JDK1.8中ArrayList是如何擴容的
ArrayList簡介:
ArrayList實現(xiàn)了List接口它是一個可調整大小的數(shù)組可以用來存放各種形式的數(shù)據。并提供了包括CRUD在內的多種方法可以對數(shù)據進行操作但是它不是線程安全的,外ArrayList按照插入的順序來存放數(shù)據。
在講擴容機制之前,我們需要了解一下ArrayList中最主要的幾個變量:
private static final int DEFAULT_CAPACITY = 10;//數(shù)組默認初始容量
private static final Object[] EMPTY_ELEMENTDATA = {};//定義一個空的數(shù)組實例以供其他需要用到空數(shù)組的地方調用
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//定義一個空數(shù)組,跟前面的區(qū)別就是這個空數(shù)組是用來判斷ArrayList第一添加數(shù)據的時候要擴容多少。默認的構造器情況下返回這個空數(shù)組
transient Object[] elementData;//數(shù)據存的地方它的容量就是這個數(shù)組的長度,同時只要是使用默認構造器(DEFAULTCAPACITY_EMPTY_ELEMENTDATA )第一次添加數(shù)據的時候容量擴容為DEFAULT_CAPACITY = 10
private int size;//當前數(shù)組的長度
本題的所有的講解都是基于JDK8

這道題考察了ArrayList的構造器和對擴容機制的了解,本篇博客基于此出發(fā)講解ArrayList的擴容機制
想要做出這道題必須了解ArrayList的構造函數(shù),ArrayList的構造函數(shù)總共有三個:
ArrayList()構造一個空的數(shù)組。JDK7中構造一個初始容量為10的空列表但是JDK8中只是構造一個空的數(shù)組ArrayList(Collection<? extends E> c)構造一個包含指定 collection 的元素的數(shù)組,這些元素是按照該 collection 的迭代器返回它們的順序排列的。ArrayList(int initialCapacity)構造一個具有指定初始容量的空數(shù)組。
我們重點來看這兩個ArrayList(int initialCapacity),ArrayList()構造函數(shù)
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
初始化一個空數(shù)組,這是JDK8不同于之前版本的地方
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
對于形參initialCapacity判斷,如果大于0那么就聲明一個和形參一樣大小的數(shù)組。了解到這里似乎這道題的正確答案也出來了即選擇A,并沒有發(fā)生擴容
但是作為一名合格的程序員要有探索精神,題目提到了擴容,既然ArrayList底層是一個數(shù)組,那么就肯定會滿,什么時候發(fā)生擴容呢?
//1.add方法為添加元素在數(shù)組末尾
public boolean add(E e) {
//確保數(shù)組容量 size指向數(shù)組的末尾
ensureCapacityInternal(size + 1);
//在完成添加之前要確保數(shù)組長度足夠
elementData[size++] = e;
return true;
}
//3.elementData為ArrayList底層維護的數(shù)組,minCapacity為此時數(shù)組的大小
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果數(shù)組為初始化的值,就初始化數(shù)組容量為10(空參的構造方法下首次添加)
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//2.minCapacity表示此時數(shù)組的大小
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//4.minCapacity表示此時數(shù)組的大小
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
//如果此時數(shù)組容量的大小不夠就擴容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
源碼讀到這里,我們明白了,當我們每次向ArrayList添加元素的時候,都會首先確保數(shù)組容量夠放下元素如果不夠就會 grow(minCapacity)調用擴容函數(shù),那么秉承著探索的精神,原本大小的數(shù)組擴容之后變成多大了呢?還得繼續(xù)看源碼
//擴容源碼
private void grow(int minCapacity) {
//獲取當前數(shù)組的長度
int oldCapacity = elementData.length;
//>>右移相當于整除2,新容量相當于就舊容量的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果擴容后的容量還不夠那么就以需要的容量為新容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新容量已經超過最大容量了,那么就直接使用最大容量
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//講新容量的數(shù)組拷貝
elementData = Arrays.copyOf(elementData, newCapacity);
}
源碼大致讀完后,我們明白了ArrayList的自動擴容機制,每次新添加元素的時候都會判斷是否能夠容下,如果不夠就會發(fā)生擴容,擴容的大小為原大小的1.5倍數(shù),明白這些以后讓我們看看下面這段程序擴容了幾次呢??容量是多少呢?
ArrayList<Integer> arrayList = new ArrayList<Integer>(20);
for(int i=1;i<=50;i++) {
arrayList.add(i);
}
前20次添加不會發(fā)生擴容,當21元素添加時數(shù)組容量從20擴容到30,當添加31元素時數(shù)組容量從30擴容到45,當添加46元素時數(shù)組容量從45擴容到67
到此這篇關于JDK1.8中ArrayList是如何擴容的的文章就介紹到這了,更多相關JDK1.8 ArrayList擴容內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Mybatis批量更新對象數(shù)據的兩種實現(xiàn)方式
這篇文章主要介紹了Mybatis批量更新對象數(shù)據的兩種實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
SpringBoot項目設置斷點debug調試無效忽略web.xml問題的解決
這篇文章主要介紹了SpringBoot項目設置斷點debug調試無效忽略web.xml問題的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-08-08
SpringCloud使用CircuitBreaker實現(xiàn)熔斷器的詳細步驟
在微服務架構中,服務之間的依賴調用非常頻繁,當一個下游服務因高負載或故障導致響應變慢或不可用時,可能會引發(fā)上游服務的級聯(lián)故障,最終導致整個系統(tǒng)崩潰,熔斷器是解決這類問題的關鍵模式之一,Spring Cloud提供了對熔斷器的支持,本文將詳細介紹如何集成和使用它2025-02-02
SpringBoot?快速實現(xiàn)?api?接口加解密功能
在項目中,為了保證數(shù)據的安全,我們常常會對傳遞的數(shù)據進行加密,Spring?Boot接口加密,可以對返回值、參數(shù)值通過注解的方式自動加解密,這篇文章主要介紹了SpringBoot?快速實現(xiàn)?api?接口加解密功能,感興趣的朋友一起看看吧2023-10-10
SpringBoot項目中使用@Scheduled讀取動態(tài)參數(shù)
這篇文章主要介紹了SpringBoot項目中使用@Scheduled讀取動態(tài)參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
SpringBoot中給指定接口加上權限校驗的實現(xiàn)
本文介紹了使用SpringSecurity為接口添加權限校驗,以防止外部訪問并確保安全性,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-12-12

