Java ArrayList源碼深入分析
1.ArrayList 是基數(shù)組結(jié)構(gòu)的,需要連續(xù)的內(nèi)存空間
從構(gòu)造函數(shù)可以看出,ArrayList內(nèi)部用一個(gè)Object數(shù)組來(lái)保存數(shù)據(jù)。
對(duì)于無(wú)參構(gòu)造,ArrayList會(huì)創(chuàng)建一個(gè)大小為10的初始數(shù)組,第一次擴(kuò)容時(shí)會(huì)創(chuàng)建默認(rèn)大小數(shù)組。
//無(wú)參構(gòu)造函數(shù),會(huì)構(gòu)造一個(gè)空數(shù)組。第一次擴(kuò)容時(shí)會(huì)創(chuàng)默認(rèn)大小為10的數(shù)組
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] EMPTY_ELEMENTDATA = {};
//如果給定集合大小,會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)大小的數(shù)組
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);
}
}2.對(duì)于set和get方法ArrayList效率高,因?yàn)榭梢灾苯油ㄟ^(guò)下標(biāo)獲取存儲(chǔ)對(duì)象。
//直接通過(guò)角標(biāo)從數(shù)組中取出元素
public E get(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
return (E) elementData[index];
}
//set 方法,直接通過(guò)index 拿到元素,進(jìn)行修改就行。
public E set(int index, E element) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}3.對(duì)于add方法,有兩種情況:
第一種是在尾部添加,不需要移動(dòng)數(shù)組。
//Add 方法 ,在末端插入不需要
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}第二種情況在指定位置添加或插入數(shù)據(jù),則需要移動(dòng)數(shù)組,效率比較低。如果插入在第0個(gè)位置則需要移動(dòng)整個(gè)數(shù)組。
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
ensureCapacityInternal(size + 1); // Increments modCount!!
//被插入的元素在index。則移動(dòng)的數(shù)組應(yīng)該從index開(kāi)始,向后移動(dòng)一個(gè),
//移動(dòng)的數(shù)組長(zhǎng)度 size-index 從index開(kāi)始的數(shù)組長(zhǎng)度
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}在add時(shí)還需要考慮到數(shù)組的擴(kuò)容問(wèn)題,看ensureCapacityInternal方法
private void ensureCapacityInternal(int minCapacity) {
//通過(guò)無(wú)參構(gòu)造創(chuàng)建為設(shè)置初始大小時(shí),判斷條件為true
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//創(chuàng)建默認(rèn)大小的數(shù)組,初始大小是10
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}添加元素后,元素?cái)?shù)量大于數(shù)組長(zhǎng)度時(shí),進(jìn)行擴(kuò)容grow,擴(kuò)容大小是原數(shù)組的1.5倍
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
//新增后,數(shù)組容量已經(jīng)大于了數(shù)組長(zhǎng)度,則進(jìn)行擴(kuò)容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//新的數(shù)組大小是原來(lái)的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//創(chuàng)建一個(gè)新長(zhǎng)度的數(shù)組。
elementData = Arrays.copyOf(elementData, newCapacity);
}4.對(duì)應(yīng)remove 刪除元素操作。如果刪除元素在最后一個(gè),不需要移動(dòng)數(shù)組,否則會(huì)將被刪除元素之后的所有元素都要向前移動(dòng),效率比較低。
//刪除
public E remove(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
modCount++;
//取出被刪除的元素
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
//移動(dòng)的數(shù)組長(zhǎng)度,大于0才需要移動(dòng),小于0說(shuō)明被刪元素在最后一個(gè)
if (numMoved > 0)
//第一個(gè)參數(shù)是源數(shù)組,
//第二個(gè)參數(shù)是移動(dòng)的起始位置:index+1,從被刪元素的后一個(gè)位置開(kāi)始
//第三個(gè)參數(shù)是目標(biāo)數(shù)組
//第四個(gè)參數(shù)是移動(dòng)目標(biāo)位置:index,被刪除元素的位置
//第五個(gè)參數(shù)是移動(dòng)的數(shù)組長(zhǎng)度 size - index - 1,從index+1位置開(kāi)始之后的數(shù)組長(zhǎng)度
//最終會(huì)調(diào)用到native方法進(jìn)行移動(dòng)。
System.arraycopy(elementData, index+1, elementData, index,numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}5.System.arraycopy方法參數(shù)分析。

第二個(gè)參數(shù) index+1是被移動(dòng)數(shù)組的起始位置,即被刪元素后一個(gè)位置
第四個(gè)參數(shù)index,是被移動(dòng)數(shù)組的起始位置,即被刪元素的位置。
最后一個(gè)參數(shù)size-index-1,被移動(dòng)數(shù)組的長(zhǎng)度,即被刪元素后一個(gè)位置到元素末尾的長(zhǎng)度
public static native void arraycopy(java.lang.Object src, int srcPos, java.lang.Object dest, int destPos, int length);
通過(guò)對(duì)源碼的閱讀,也許會(huì)對(duì)ArrayList有一個(gè)更加直接的了解。
到此這篇關(guān)于Java ArrayList源碼深入分析的文章就介紹到這了,更多相關(guān)Java ArrayList內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android應(yīng)用隱私合規(guī)檢測(cè)實(shí)現(xiàn)方案詳解
這篇文章主要介紹了Android應(yīng)用隱私合規(guī)檢測(cè)實(shí)現(xiàn)方案,我們需要做的就是提前檢測(cè)好自己的應(yīng)用是否存在隱私合規(guī)問(wèn)題,及時(shí)整改過(guò)來(lái),下面提供Xposed Hook思路去檢測(cè)隱私合規(guī)問(wèn)題,建議有Xposed基礎(chǔ)的童鞋閱讀,需要的朋友可以參考下2022-07-07
Android實(shí)現(xiàn)便于批量操作可多選的圖片ListView實(shí)例
這篇文章主要介紹了Android實(shí)現(xiàn)便于批量操作可多選的圖片ListView功能實(shí)現(xiàn)方法,涉及ListView針對(duì)多圖操作的相關(guān)技巧,需要的朋友可以參考下2016-08-08
Android App中使用ListFragment的實(shí)例教程
這篇文章主要介紹了Android App中使用ListFragment的實(shí)例教程,ListFragment的內(nèi)容是以列表(list)的形式顯示的Fragment,需要的朋友可以參考下2016-05-05
Android Studio Gradle插件版本與Gradle版本之間的對(duì)應(yīng)關(guān)系
今天小編就為大家分享一篇關(guān)于Android Studio Gradle插件版本與Gradle版本之間的對(duì)應(yīng)關(guān)系,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
ActivityManagerService之Service啟動(dòng)過(guò)程解析
這篇文章主要為大家介紹了ActivityManagerService之Service啟動(dòng)過(guò)程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Android使用Websocket實(shí)現(xiàn)聊天室
這篇文章主要為大家詳細(xì)介紹了Android使用Websocket實(shí)現(xiàn)聊天室,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
RecyclerView實(shí)現(xiàn)側(cè)滑拖拽功能
這篇文章主要為大家詳細(xì)介紹了RecyclerView實(shí)現(xiàn)側(cè)滑拖拽功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07

