List --- ArrayList源碼解析

 

本文采用的是jdk1.8,分析ArrayList常用的方法源碼;如有錯誤,請指出,謝謝

 

一,ArrayList的關係圖

在我們日常開發階段,ArrayList是我們用的非常非常多的一個集合,帶來了很大的便利,下面開始分析ArrayList的源碼

 

二,源碼分析

2.1屬性分析

從ArrayList的屬性,我們可以很清楚的看出:ArrayList的底層就是一個數組的形式,ArrayList中有擴容的概念,正式因爲有擴容,所有它能實現動態增長

 

2.2 構造方法

 

2.3 add方法

add()方法是我們常用的方法,可以說是ArrayList比較重要的方法了,下面我們來看看:

2.3.1 add(E e)

步驟:

  • 檢查是否需要擴容
  • 插入元素

首先先看看這個方法

 public boolean add(E e) {
        //確定list的容量,嘗試容量加1
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //添加元素
        elementData[size++] = e;
        return true;
    }

這個方法主要就是幹兩件事:

  • 確定list的容量,嘗試容量+1,看有沒有擴容的必要
  • 添加元素

接下來進入ensureCapacityInternal()方法,看看容量的的添加過程

隨後調用ensureExplicitCapacity()來確定明確的容量,我們也來看看這個方法是怎麼實現的:

接下來看看grow()對數組的擴容過程

進入copyOf()方法看看是如何移動數組的

我們再進入arraycopy()裏看看

該方法帶有native修飾符,就可以知道是C/C++去寫的,並非java來實現的,總的來說arraycopy()是一個比較高效可靠的方法

 

到目前爲止,我們可以知道add(E e)的基本實現了:

>>首先去檢查一下數組的容量是否足夠

>>>>足夠,直接添加元素

>>>>不足夠,擴容數組

>>>>>>擴容都原來的1.5倍

>>>>>>第一次擴容後,如果容量還是小於minCapacity,就將容量擴充爲minCapacity

 

2.3.2 add(int index, E element)

步驟:

  • 檢查角標
  • 檢查是否需要擴容
  • 插入元素

下面這個是插入的實現:

2.4 get()

步驟:

  • 檢查角標
  • 返回元素

接下來我們看看rangeCheck()和elementData()兩個方法:

 

2.5  set(int index, E element)

步驟:

  • 檢查角標
  • 替代元素
  • 返回舊值

 

2.6 remove(int index)

步驟

  • 檢查角標
  • 計算要移動的個數,並移動
  • 將最後一個元素設爲null(刪除),讓gc進行回收

 

 

2.7 細節說明

  • ArrayList是基於動態數組實現的,在增刪時候,需要數組的拷貝複製
  • ArrayList的默認初始化容量是10,每次擴容時候增加原先容量的一半,也就是變爲原來的1.5倍
  • 刪除元素時不會減少容量,若希望減少容量則調用trimToSize()
  • 它不是線程安全的。它能存放null值。

 

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