java集合系列03:ArrayList解析

轉載自:http://www.cnblogs.com/skywang12345/p/3308556.html

第1部分 ArrayList介紹

ArrayList簡介

ArrayList 是一個數組隊列,相當於 動態數組。與Java中的數組相比,它的容量能動態增長。它繼承於AbstractList,實現了List, RandomAccess, Cloneable, java.io.Serializable這些接口。

ArrayList 繼承了AbstractList,實現了List。它是一個數組隊列,提供了相關的添加、刪除、修改、遍歷等功能。
ArrayList 實現了RandmoAccess接口,即提供了隨機訪問功能。RandmoAccess是java中用來被List實現,爲List提供快速訪問功能的。在ArrayList中,我們即可以通過元素的序號快速獲取元素對象;這就是快速隨機訪問。稍後,我們會比較List的“快速隨機訪問”和“通過Iterator迭代器訪問”的效率。

ArrayList 實現了Cloneable接口,即覆蓋了函數clone(),能被克隆。

ArrayList 實現java.io.Serializable接口,這意味着ArrayList支持序列化,能通過序列化去傳輸。

 

和Vector不同,ArrayList中的操作不是線程安全的所以,建議在單線程中才使用ArrayList,而在多線程中可以選擇Vector或者CopyOnWriteArrayList。

ArrayList構造函數
// 默認構造函數
ArrayList()

// capacity是ArrayList的默認容量大小。當由於增加數據導致容量不足時,容量會添加上一次容量大小的一半。
ArrayList(int capacity)

// 創建一個包含collection的ArrayList
ArrayList(Collection<? extends E> collection)ArrayList的API             

ArrayList的API

// Collection中定義的API
boolean             add(E object)
boolean             addAll(Collection<? extends E> collection)
void                clear()
boolean             contains(Object object)
boolean             containsAll(Collection<?> collection)
boolean             equals(Object object)
int                 hashCode()
boolean             isEmpty()
Iterator<E>         iterator()
boolean             remove(Object object)
boolean             removeAll(Collection<?> collection)
boolean             retainAll(Collection<?> collection)
int                 size()
<T> T[]             toArray(T[] array)
Object[]            toArray()
// AbstractCollection中定義的API
void                add(int location, E object)
boolean             addAll(int location, Collection<? extends E> collection)
E                   get(int location)
int                 indexOf(Object object)
int                 lastIndexOf(Object object)
ListIterator<E>     listIterator(int location)
ListIterator<E>     listIterator()
E                   remove(int location)
E                   set(int location, E object)
List<E>             subList(int start, int end)
// ArrayList新增的API
Object               clone()
void                 ensureCapacity(int minimumCapacity)
void                 trimToSize()
void                 removeRange(int fromIndex, int toIndex)

第2部分 ArrayList數據結構

ArrayList的繼承關係

java.lang.Object
   ↳     java.util.AbstractCollection<E>
         ↳     java.util.AbstractList<E>
               ↳     java.util.ArrayList<E>

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}

ArrayList與Collection關係如下圖

ArrayList包含了兩個重要的對象:elementData 和 size

(01) elementData 是"Object[]類型的數組",它保存了添加到ArrayList中的元素。實際上,elementData是個動態數組,我們能通過構造函數 ArrayList(int initialCapacity)來執行它的初始容量爲initialCapacity;如果通過不含參數的構造函數ArrayList()來創建ArrayList,則elementData的容量默認是10。elementData數組的大小會根據ArrayList容量的增長而動態的增長,具體的增長方式,請參考源碼分析中的ensureCapacity()函數。

(02) size 則是動態數組的實際大小。



第3部分 ArrayList源碼解析(JDK1.8)

    add(E e) 方法

  //添加一個對象到尾部
   public boolean add(E e) {
         //確保當前容量足夠,不夠則進行擴容操作
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //設置值e
        elementData[size++] = e;
        return true;
    }

     private void ensureCapacityInternal(int minCapacity) {
     //ArrayList爲空時,容量直接擴容爲10
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
             //當前需要容量不足DEFAULT_CAPACITY(10)時,直接擴爲10
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //確保得到明確需要新容量
        ensureExplicitCapacity(minCapacity);
    }
    private void ensureExplicitCapacity(int minCapacity) {
        //“發生結構”時+1,防止遍歷元素時,發生結構變更,則拋錯。
        modCount++;

        // 需要容量大於當前容量時,執行擴容操作
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    

    擴容規則

//minCapacity 當前需要的最小容量
   private void grow(int minCapacity) {
        // 當前容量
        int oldCapacity = elementData.length;
        //新容量=當前容量+當前容量的1/2
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //當新容量還是小於minCapacity時,則直接擴從至minCapacity大小
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
         //當newCapacity大於MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8)時
        if (newCapacity - MAX_ARRAY_SIZE > 0)
             // 容量過於巨大,需判斷是否發生溢出
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        // 本質還是調用Arrays內方法,完成對數組的操作!
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
 private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // 發生內存溢出,
            throw new OutOfMemoryError();
         //未發生溢出,則返回  Integer.MAX_VALUE 或  MAX_ARRAY_SIZE
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

(1)對於空的ArrayList,首次添加元素的時候,就會直接擴容至10

(2)所需容量大於當前容量時,進行擴容,擴容至當前容量的1.5倍

(3)如果擴容完後還是所需容量還是大於當前容量,直接擴容至所需容量

 clear方法


  public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

置elementData中的所有值爲null,注意不會更改elementData的大小,如果需要釋放,需要調用trimToSize方法



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