Java之ArrayList的底層原理:面試常考考點

  1. 定義
    • java.util.ArrayList類就是傳說中的動態數組,相當於Array的複雜版本,也就是說,ArrayList對象既有數組的特徵,也有列表的特徵。ArrayList實現了List接口,允許對元素進行快速隨機訪問。
  2. 結構
    image.png
  3. 源碼
  public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

   // 默認大小
    private static final int DEFAULT_CAPACITY = 10;

    // 共享的空數組,用於初始化空實例
    private static final Object[] EMPTY_ELEMENTDATA = {};

     //主要作爲一個標識位,在擴容時區分:默認大小和容量爲0,使用默認容量時採取的是“懶加載”
    //即等到add元素的時候才進行實際容量的分配
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    //ArrayList內部結構,是一個Object[]類型的數組
    transient Object[] elementData; 
    //記錄當前容器中有多少元素
    private int size;
- DEFAULT_CAPACITY :默認大小爲 10;(擴容爲原來的一半 擴容一次以後爲15)擴容使用Arrays.copyOf(elementData, size, Object[].class);
- EMPTY_ELEMENTDATA: 共享的空數組,用於初始化空實例
- Object[] elementData:ArrayList內部結構,是一個Object[]類型的數組
- size:記錄當前容器中有多少元素
  1. 構造方法
public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        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);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
//無參構造器,指向的是默認容量大小的Object數組,注意使用無參構造函數的時候並沒有直接創建容量 
//爲10的Object數組,而是採取懶加載的策略:使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA(實際容量爲0)
//作爲標識,在真正add元素時纔會開闢Object數組,即在擴容函數中有處理默認容量的邏輯,後面會有分析
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
1. public ArrayList(int initialCapacity) 構造方法:表示接受指定容量值,初始化創建數組,真正開發時候按照實際情況創建ArrayList可指定。
2. public ArrayList() 構造方法:是默認的構造方法,它創建一個空數組。
3. public ArrayList(Collection<? extends E> c) 構造方法:接收一個Collection的實體,將該Collection實體轉換爲ArrayList對象。
  1. add 添加方法
   public boolean add(E e) {
     
 
        modCount++;
 
        //add操作的核心函數,當使用無參構造器時並沒有直接分配大小爲10的Object數組,這裏面有對應 
        //的處理邏輯
        add(e, elementData, size);
        return true;
    }

  • 主要用於標識線程安全,即ArrayList只能在單線程環境下使用,在多線程環境下會出現併發安全問題,modCount主要用於記錄對ArrayList的修改次數,如果一個線程操作期間modCount發生了變化即,有多個線程同時修改當前這個ArrayList,此時會拋出“ConcurrentModificationException”異常,這又被稱爲“failFast機制”,在很多非線程安全的類中都有failFast機制:HashMap、 LinkedList等。這個機制主要用於迭代器、加強for循環等相關功能,也就是一個線程在迭代一個容器 時,如果其他線程改變了容器內的元素,迭代的這個線程會拋出“ConcurrentModificationException”異常
  1. LinkedList底層採用雙向列表實現,所以在添加新元素的時候要先構造一個Node對象(item爲我們加入的值),只需要將Node的next賦值爲新的Node即可。但是相對於ArrayList而言,LinkedList可以更加高效的插入元素,因爲它不會涉及到ArrayList擴容。但也因爲這種數據結構,導致它不具備有隨機訪問的能力。

  2. ArrayList和LinkedList都不是線程安全的。那麼如果我們要用線程安全的用什麼呢 ?

    • List list = Collections.synchronizedList(new ArrayList<>());Collections提供了方法synchronizedList保證list是同步線程安全的。
    • CopyOnWriteArrayList:寫時複製,CopyOnWrite容器既寫時複製的容器,往一個容器添加元素的時候,不直接往當前的容器Object[]添加,而是先將當前容器Object[] 進行Copy,複製出一個新的容器Object[] newElements,然後往新的容器Object[] newElement裏面添加元素,添加完元素之後,再將原容器的引用指向新的容器,setArray(newElements );這樣做的好處是可以對CopyOnWriter容器進行併發的讀,而不需要加鎖,因爲當前容器不會添加任何元素,所以CopyOnWrite容器也是一種讀寫分離的思想,讀和寫不同的容器。
    public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }
    

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gCSSDd7N-1585494592841)(https://upload-images.jianshu.io/upload_images/8123471-3db0a888e48cd3a2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章