經常使用數據結構之ArrayList

前言程序員

    ArrayList想必是廣大Java程序員開發時最經常使用的數據結構了,但不必定對其原理都有了解,今天我將結合ArrayList的源碼對其進行講解。本文將圍繞ArrayList主要特性(包括適用場景、初始大小、擴容等)、數據存放方式、核心方法實現、其餘特性等四個方面進行講解。面試

1、ArrayList特性數組

    ArrayList是基於數組的數據結構,與LinkedList相比,更加適合在查詢多、增刪操做少的場景下使用,而且它是非線程安全的,若是併發量比較大的場景,須要改用線程安全的版本或者用JUC包中的CopyOnWriteArrayList。安全

    它的初始數組大小爲10,由下圖所示的成員變量控制:數據結構

 

     當新加元素時原數組已經滿了,則會觸發擴容,擴容策略爲將原數組長度*1.5,代碼中是用右移位運算實現的,源碼以下所示:多線程

2、數據存放方式併發

    ArrayList是以數組的方式存放數據的,Object[],以下所示:this

3、核心方法實現spa

    咱們看最經常使用的add方法:線程

1 public boolean add(E e) { 2         ensureCapacityInternal(size + 1);  // 若是已經滿了,則擴容
3         elementData[size++] = e; 4         return true; 5     }

    下面方法用於判斷是否原數組已經滿了,若是滿了則擴容,不滿且未初始化則初始化長度爲10,不然不用變化

1 private void ensureCapacityInternal(int minCapacity) { 2  ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); 3     }

    下面方法用於返回數組須要的最小長度。

1 private static int calculateCapacity(Object[] elementData, int minCapacity) { 2         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 3             return Math.max(DEFAULT_CAPACITY, minCapacity); 4  } 5         return minCapacity; 6     }

    下面的方法用於判斷是否須要擴容,若是須要則經過grow方法擴容。

1 private void ensureExplicitCapacity(int minCapacity) { 2         modCount++; 3 
4         // overflow-conscious code
5         if (minCapacity - elementData.length > 0) // 若是須要的最小長度大於當前數組總長度,則走grow擴容 6  grow(minCapacity); 7     }

    下面的grow方法是控制擴容的核心方法:

 1 private void grow(int minCapacity) {  2         // overflow-conscious code
 3         int oldCapacity = elementData.length;  4         int newCapacity = oldCapacity + (oldCapacity >> 1);  5         if (newCapacity - minCapacity < 0) // 若是擴容以後的長度小於須要的最小長度,則取最小長度爲待擴容長度,這種狀況通常不會出現  6             newCapacity = minCapacity;  7         if (newCapacity - MAX_ARRAY_SIZE > 0)  8             newCapacity = hugeCapacity(minCapacity);  9         // minCapacity is usually close to size, so this is a win:
10         elementData = Arrays.copyOf(elementData, newCapacity); // 建立新數組,將老數組的數據複製過去 11     }

    注意複製數組時,用的Arrays.copyOf方法,該方法最終引用的是System.arraycopy這個native方法實現的數組複製。其餘方法更加簡單,此處就不一一粘貼源碼解讀了。

4、其餘特性

一、關於modCount

    在看ArrayList源碼的時候,會發現有一個變量是modCount,在增刪改的方法中均涉及到對它的++操做。modCount屬性是在AbstractList中定義出來的:

 

    能夠把它理解成每一個ArrayList的一個改動的版本號,只要ArrayList有改動,這個版本號就會+1。在經過迭代器對ArrayList裏面的元素進行遍歷操做時,每次都會比較一下這個版本號是否有變化,若是檢測到預期以外的變化,就會拋出常見的那個異常-ConcurrentModificationException:

 

    ArrayList東西很少,實現也相對比較簡單,面試時如今通常會跟Vector或者LinkedList進行比對或者做爲多線程的一個引子來問,本文就先到這裏,下一期對LinkedList進行解讀。

相關文章
相關標籤/搜索