java数组扩容arraylist,ArrayList--扩容机制
ArrayList簡介
ArrayList是一個動態數組,它的容量可以動態增長,默認容量是10,每次擴容都為原來容量的1.5倍 。 從如下類定義可以看到,它繼承了AbstractList,并實現了List/RandomAccess/Cloneable/java.io.Serializable接口
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
1.繼承AbstractList和實現List接口,使得ArrayList有了增刪改和遍歷數組的功能
2.實現RandomAccess接口,即可以隨即訪問List內的元素,區別于通過Interator迭代器訪問
3 這里輸入引用文本3.實現java.io.Serializable接口,即可以序列化。
ArrayList兩個重要成員變量
1.elementData,是Object[]。Object類型數組里面保存著ArrayList的元素
/**
* Object[]數組,保存ArrayList數據
*/
transient Object[] elementData;
2.size,即ArrayList的實際大小
/**
* ArrayList的實際大小(即保存元素的個數)
*/
private int size;
3個構造器:ArrayList容量的初始化
1.默認構造器 public ArrayList()
2.指定容量的構造器 public ArrayList(int initialCapacity)
3.將其他集合轉成ArrayList的構造器 public ArrayList(Collection extends E> c)
其中,默認構造器初始化容量大小為10
/**
* 默認構造函數,初始容量為10
*/
private static final int DEFAULT_CAPACITY = 10;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
ArrayList源碼解析
兩個擴容函數,根據 期望容量minCapacity 來擴大ArrayList容量
public void ensureCapacity(int minCapacity) {
/*
* 【minExpand 計算】若 elementData 不為默認大小的空Object[]數組,
* 那么minExpand就為0,否則 minExpand 為 DEFAULT_CAPACITY
*/
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
? 0
// larger than default for default empty table. It's already
// supposed to be at default size.
: DEFAULT_CAPACITY;
/*
* 【minCapacity 與 minExpand 比較】當 “期望容量 > 最小可擴展容量” 時
* 根據 期望容量 去擴容。也就是說想要擴容, minCapacity 一定大于 minExpand
*/
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
private void ensureCapacityInternal(int minCapacity) {
/*
* 【確定minCapacity】若ArrayList是默認大小的空Object[]數組,則取
* minCapacity 和 DEFAULT_CAPACITY 中的最大值
*/
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
// 直接擴容。根據 期望容量 來擴大ArrayList容量
ensureExplicitCapacity(minCapacity);
}
ensureCapacity()與ensureCapacityInternal()的區別是:
1、前者不一定擴容,只有當minCapacity > minExpand 時擴容(有條件的調用ensureExplicitCapacity())。
2、后者一定擴容(直接調用ensureExplicitCapacity())
當向ArrayList增加元素的時候,判斷ArrayList容量是否足夠的函數ensureExplicitCapacity() 若 期望容量 > 可用容量,即原ArrayList的可用容量已經不夠用了,則調用grow()函數來擴大ArrayList容量,容量大小為minCapacity
private void ensureExplicitCapacity(int minCapacity) {
modCount++; // Increment!
// 若 期望容量 > ArrayList可用容量
if (minCapacity - elementData.length > 0)
// 調用grow()擴容
grow(minCapacity);
}
對于grow(),值得注意的是擴容后新容量的大小:基于原容量*3/2與 期望容量minCapacity大小比較。 若 *3/2 > minCapacity,新容量 = 原容量的3/2 若 *3/2 < minCapacity,新容量 = minCapacity 反正總的一個原則:取值比較大的就對了
???那么問題就來了,是否新容量可以無限大? 函數hugeCapacity()給出了答案,如下。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 【基于原容量定新容量,且一定執行】新容量 = 原容量*3/2
int newCapacity = oldCapacity + (oldCapacity >> 1);
/*
* 【newCapacity取大 (已經擴容一次了,*3/2)】若 (新容量 < 企圖容量) ,
* 則 (新容量 = 企圖容量),反正取最大就是了。PS:這次比較的是
* (*3/2)與 minCapacity,取大者
*/
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
/*
* 【上限,在合理范圍內擴容】這個范圍就是數組和整型值的范圍,最大值為
* MAX_ARRAY_SIZE(上限) 和 Integer.MAX_VALUE(上限)。
* 若 (企圖容量 > MAX_ARRAY_SIZE),那么說明 MAX_ARRAY_SIZE 不能滿足
* 需求大小,則用 Integer.MAX_VALUE
*/
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 前面千辛萬苦得到合適的 newCapacity 后,終于可以開始擴容了,調用 .copyOf()
elementData = Arrays.copyOf(elementData, newCapacity);
}
Integer.MAX_VALUE和 MAX_ARRAY_SIZE之間的關系,如下:
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
可見,Integer.MAX_VALUE > MAX_ARRAY_SIZE > 0,而 擴容后的新容量在(0,Integer.MAX_VALUE]的左開右閉區間內。
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的java数组扩容arraylist,ArrayList--扩容机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开启php的ssl,php怎么开启ssl
- 下一篇: mysql倍增表的内容,mysql -