1. 程式人生 > >【數組】- ArrayList自動擴容機制

【數組】- ArrayList自動擴容機制

exceptio ++ 表示 io操作 leg 當前 arraylist all length

  不同的JDK版本的擴容機制可能有差異 實驗環境:JDK1.8
  
  擴容機制:
  
  當向ArrayList中添加元素的時候,ArrayList如果要滿足新元素的存儲超過ArrayList存儲新元素前的存儲能力,ArrayList會增強自身的存儲能力,已達到存儲新元素的要求
  
  ArrayList:本質通過內部維護的數組對象進行數據存儲
  
  ①:分析ArrayList的add(E)方法
  
  public boolean add(E e) {
  
  ensureCapacityInternal(size + 1); // Increments modCount!!
  
  elementData[size++] = e;
  
  return true;
  
  }
  
  分析:add方法首先通過ensureCapacityInternal()方法確保當前ArrayList維護的數組具有存儲新元素的能力,經過處理之後將元素存儲在數組elementData的尾部 elementData:ArrayList真正用於存儲元素的數組
  
  ②:分析ensureCapacityInternal方法
  
  private void ensureCapacityInternal(int minCapacity) {
  
  if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  
  minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
  
  }
  
  ensureExplicitCapacity(minCapacity);
  
  }
  
  分析:ensureCapacityInternal判斷ArrayList默認的元素存儲數據是否為空,為空則設置最小要求的存儲能力為必要存儲的元素和默認存儲元素個數的兩個數據之間的最大值,然後調用ensureExplicitCapacity方法實現這種最低要求的存儲能力
  
  註意:ArrayList的存儲空間並不是需要一個創建一個,而是分階段性的創建,一般會預留存儲空間。 例如,如果ArrayList需要存儲10個元素,恰好ArrayList只能存儲6個元素,剩余4個元素無法存儲,ArrayList可能會一次性擴展10個元素,這種ArrayList就有20個元素的存儲能力,在存儲能力範圍內,下次再存放元素,就不需要再次擴容
  
  ③:分析ensureExplicitCapacity方法:
  
  private void ensureExplicitCapacity(int minCapacity) {
  
  modCount++;
  
  // overflow-conscious code
  
  if (minCapacity - elementData.length > 0)
  
  grow(minCapacity);
  
  }
  
  分析:如果最低要求的存儲能力>ArrayList已有的存儲能力,這就表示ArrayList的存儲能力不足,因此需要調用 grow();方法進行擴容 ④:分析grow()方法
  
  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);
  
  }
  
  分析:當ArrayList擴容的時候,首先會設置新的存儲能力為原來的1.5倍
  
  int newCapacity = oldCapacity + (oldCapacity www.michenggw.com>> 1);
  
  如果擴容之後還是不能滿足要求則MAX_ARRAY_SIZE比較,求取最大值, 如果MAX_ARRAY_SIZE大小的能力還是不能滿足則通過hugeCapacity()方法獲取ArrayList能允許的最大值:
  
  private static int hugeCapacity(int minCapacity) {
  
  if (minCapacity < 0) // overflow
  
  throw new OutOfMemoryError();
  
  return (minCapacity > MAX_ARRAY_SIZE) ?
  
  Integer.MAX_VALUE :
  
  MAX_ARRAY_SIZE;
  
  }
  
  從hugeCapacity方法看出,ArrayList最大的存儲能力:存儲元素的個數為整型的範圍。 確定ArrayList擴容之後最新的可存儲元素個數時,調用 elementData = Arrays.copyOf(elementData, newCapacity); 實現elementData數組的擴容,整個流程就是ArrayList的自動擴容機制工作流程
  
  擴展: ArrayList的自動擴容機制底層借助於System實現
  
  public static native void arraycopy
  
  (Object src, int srcPos,
  
  Object dest, int destPos,
  
  int length);
  
  arraycopy標識為native意味JDK的本地庫,不可避免的會進行IO操作,如果頻繁的對ArrayList進行擴容,毫不疑問會降低ArrayList的使用性能,因此當我們確定添加元素的個數的時候,我們可以事先知道並指定ArrayList的可存儲元素的個數,這樣當我們向ArrayList中加入元素的時候,就可以避免ArrayList的自動擴容,從而提高ArrayList的性能
  
  ArrayList含參構造函數:初始化時指定存儲元素的能力:
  
  public ArrayList(int initialCapacity) {
  
  if (initialCapacity www.dasheng178.com> 0) {
  
  this.elementData = new Object[initialCapacity];
  
  } else if (initialCapacity == 0) {
  
  this.elementData = EMPTY_ELEMENTDATA;
  
  } else {
  
  throw new IllegalArgumentException(
  
  "Illegal Capacity: "+initialCapacity);
  
  }

【數組】- ArrayList自動擴容機制