ArrayList做爲java中經常使用的集合類型有哪些特色須要咱們瞭解呢?本文將基於jdk1.8源碼來一步步列出ArrayList有哪些須要使人注意的要點。java
ArrayList繼承實現關係以下圖:數組
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
從該圖咱們能夠看出,ArrayList實現了RandmoAccess接口,RandmoAcess接口實現以下:dom
public interface RandomAccess { }
RandmoAccess接口中實際上並沒有任何實現,該接口只是表示實現了該接口的類可以提供快速訪問功能。this
ArrayList實現了RandmoAccess接口表明可以進行快速訪問,而ArrayList的快速訪問功能其實是靠數組實現的,下面是ArrayList中最重要的兩個屬性:code
//ArrayList實際存數據的地方 transient Object[] elementData; //ArrayList的大小 private int size;
下面咱們來看ArrayList的默認構造方法:繼承
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
默認構造方法會將elementData屬性賦爲DEFAULTCAPACITY_EMPTY_ELEMENTDATA,其中DEFAULTCAPACITY_EMPTY_ELEMENTDATA屬性是一個空數組接口
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
接下來咱們看ArrayList中的add和get方法:ci
public boolean add(E e) { //確認是否擴容 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } public E get(int index) { //檢查是否越界 rangeCheck(index); return elementData(index); }
能夠看出Arraylist底層是經過數組來操做的。element
ArrayList使用默認構造器建立類時建立的是一個空的數組,那麼ArrayList是如何可以使用add方法存數據的呢?咱們能夠詳細看看add方法中的ensureCapacityInternal方法源碼:rem
private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //DEFAULT_CAPACITY常量數值是10 return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureExplicitCapacity(int minCapacity) { //記錄修改次數 modCount++; if (minCapacity - elementData.length > 0) //擴容方法 grow(minCapacity); }
從以上源碼能夠看出當ArrayList爲一個空數組時,會賦予一個默認的擴容大小10,而後再進擴容方法裏擴容ArrayList,所以ArrayList使用默認構造器初始化時,不會立馬初始化數組大小,而是等待調用add方法後纔會進行初始化,且初始化大小爲10。
咱們能夠查看ArrayList的grow方法來看看arrayList實際是如何擴容的:
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; //位運算1.5倍擴容 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) //判斷minCapacity是否超出最大整數值 newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
以上代碼分爲以下幾個步驟: