ArrayList的原始碼分析(基於jdk1.8)
阿新 • • 發佈:2018-12-18
1.初始化
transient Object[] elementData; //實際儲存元素的陣列 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; public ArrayList() { //初始化為一個預設的空陣列 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
2. 新增元素
private static final int DEFAULT_CAPACITY = 10;//預設容量 publicboolean add(E e) { //確保當前陣列的容量是夠得 ensureCapacityInternal(size + 1); // Increments modCount!! //將新元素新增到[size++]的位置 elementData[size++] = e; return true; }
private void ensureCapacityInternal(int minCapacity) { //如果是第一次新增 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //擴容為預設容量大小:10 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } //每一次新增都要判斷是否需要擴容 ensureExplicitCapacity(minCapacity); }
3.擴容
private void ensureExplicitCapacity(int minCapacity) { modCount++; // 如果需要擴容 if (minCapacity - elementData.length > 0) grow(minCapacity); }private void grow(int minCapacity) { // 先獲取當前陣列的容量 int oldCapacity = elementData.length; //新容量為當前容量 + 當前容量的一半 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 拷貝原陣列中的元素至新陣列,並返回新陣列的引用 elementData = Arrays.copyOf(elementData, newCapacity); }
4.結論
ArrayList物理結構是陣列,決定了它的儲存特點是:需要開闢連續的儲存空間來儲存元素,當儲存容量不夠時,需要擴容,增加容量為原來的1.5倍。類似的,Vector的物理結構也是陣列,當儲存容量不夠時,需要擴容為原來的2倍。那麼是1.5倍好呢?還是2倍好呢?1.5倍使得陣列空間使用率提高了,但是這也增加了擴容的頻率。所以,建議大家在選擇動態陣列時,如果對要儲存的元素個數有一個預估時,那麼可以在建立ArrayList時,就使用ArrayList(int initialCapacity) 構造器,避免反覆擴容。