基於jdk8
1.首先我們看new ArrayList中
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
ArrayList底層就是一個Object數組;
這里DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一個靜態的空的Object數組,所以ArrayList初始容量實際是0;
2.add方法
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private int size;
這里size默認值為0
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private static final int DEFAULT_CAPACITY = 10;
默認DEFAULT_CAPACITY容量為10,但是這是在使用add方法時,ArrayList才會進行初始化容量賦值。
首次加載時,elementData 對象肯定是一個空的Object數組,所以minCapacity = 10;
3.接下來我們再看看ensureExplicitCapacity這個方法;
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
首次加載時minCapacity = 10,所以minCapacity - elementData.length肯定大於0,然后進行擴容判斷
還有就是當數組大小超過原有容量之后會進行擴容。擴容大小為 old +(old/2) -->1.5倍
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
初次加載,oldCapacity = 0,所以newCapacity=0;newCapacity - minCapacity <0,所以最后初始化加載時newCapacity 為10了。
最后 newCapacity 會與MAX_ARRAY_SIZE進行比較,不能超過Integer的最大值減8
The maximum size of array to allocate.
Some VMs reserve some header words in an array.
Attempts to allocate larger arrays may result in
OutOfMemoryError: Requested array size exceeds VM limit
vm虛擬機會在數組中存放一些數據,所以不能等於Integer.MAX_VALUE(2147483647)
private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE)? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
--拓展--
因為ArrayList底層是一個Object數組,在多線程環境中可以會出現並發爭搶的問題,
java提供三種解決方案:
1.new Vector jdk1.0就出現的類
public void add(E e) { int i = cursor; synchronized (Vector.this) { checkForComodification(); Vector.this.add(i, e); expectedModCount = modCount; } cursor = i + 1; lastRet = -1; }
加了synchronized保證add方法線程安全性,但是並發性急劇下降,所以在jdk1.2中才
會出現ArrayList這個類。
2.Collections.SynchronizedList(new ArrayList());
public boolean add(E e) { synchronized (mutex) {return c.add(e);} }
3.new CopyOnWriteArrayList();
private transient volatile Object[] array;
使用volatile關鍵字,保證array數組可見性,禁止指令重排;
public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }
add方法添加ReentrantLock 可重入鎖(遞歸鎖),保證add方法在多線程環境中程序執行
的安全性。