原始碼分析:ArrayList擴容機制
ArrayList是我比較常用的Java容器,最近研究了一下它的底層實現部分。關於ArrayList的繼承關係請參考上一篇文章ofollow,noindex">Java容器概覽 。
成員變數
private static final long serialVersionUID = 8683452581122892189L; //預設的初始容量為10 private static final int DEFAULT_CAPACITY = 10; //定義一個空的陣列例項以供其他需要用到空陣列的地方呼叫 private static final Object[] EMPTY_ELEMENTDATA = {}; //定義一個空陣列,跟前面的區別就是這個空陣列是用來判斷ArrayList第一新增資料的時候要擴容多少。預設的構造器情況下返回這個空陣列 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //資料存的地方,它的容量就是這個陣列的長度,同時只要是使用預設構造器(DEFAULTCAPACITY_EMPTY_ELEMENTDATA )第一次新增資料的時候容量擴容為DEFAULT_CAPACITY = 10 transient Object[] elementData; // ArrayList中實際資料的數量 private int size;
構造方法
public ArrayList()//無參建構函式,預設容量為10 { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } public ArrayList(Collection<? extends E> c)//建立一個包含collection的ArrayList { elementData = c.toArray(); //返回包含c所有元素的陣列 if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class);//複製指定陣列,使elementData具有指定長度 } else { //c中沒有元素 this.elementData = EMPTY_ELEMENTDATA; } } public ArrayList(int initialCapacity) //帶初始容量大小的建構函式 { if (initialCapacity > 0)//初始容量大於0,例項化陣列 { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) //初始化等於0,將空陣列賦給elementData { this.elementData = EMPTY_ELEMENTDATA; } else//初始容量小於,拋異常 { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
擴容
//擴容由add方法引起 public boolean add(E e) { ensureCapacityInternal(size + 1);// Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { //快速報錯機制 modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } //ArrayList擴容的核心方法,此方法用來決定擴容量 private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; //注意此處擴充capacity的方式是將其向右一位再加上原來的數,實際上是擴充了1.5倍 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 int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
總結一下:
if (elementData== DEFAULTCAPACITY_EMPTY_ELEMENTDATA)