Java集合:ArrayList使用詳解及源碼分析

1 使用方法

  ArrayList是數組隊列,可以實現容量的動態增長。ArrayList類繼承了AbstractList抽象類並且實現了List、RandomAccess,Cloneable以及java.io.Serializable接口。
public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable
AbstractList類繼承了AbstractCollection類並實現了List接口。
  實現RandomAccess接口使ArrayList擁有隨機訪問的能力,即通過下表索引訪問數組元素。
  實現Cloneable接口重寫了接口定義的clone()方法,ArrayList可以使用clone()複製數組。
  實現 java.io.Serializable接口使ArrayList支持序列化。

1.1 方法介紹

  ArrayList提供了增加、刪除、判空等操作,具體提供的方法如下:

// Collection中定義的API
boolean             add(E object)  //增加元素
boolean             addAll(Collection<? extends E> collection) //複製另一個Collection中的所有元素
void                clear() //清空數組
boolean             contains(Object object) //判斷數組中是否包含object
boolean             containsAll(Collection<?> collection) //判斷另一個數組是否是這個數組的子集
boolean             equals(Object object) //判斷元素是否相等
int                 hashCode() //獲取hash code
boolean             isEmpty() //判空
Iterator<E>         iterator() //迭代器
boolean             remove(Object object) //刪除元素
boolean             removeAll(Collection<?> collection)  //刪除collection包含的元素
boolean             retainAll(Collection<?> collection) //保留collection包含的元素
int                 size() //獲取數組大小
<T> T[]             toArray(T[] array)  //轉換成T類型的數組
Object[]            toArray() //轉換成Object類型的數組
// AbstractCollection中定義的API
void                add(int location, E object) //指定位置增加元素
boolean             addAll(int location, Collection<? extends E> collection) //指定位置開始增加多個元素
E                   get(int location) //獲取location位置的元素
int                 indexOf(Object object) //獲取object首次出現的位置
int                 lastIndexOf(Object object) //獲取object最後一次出現的位置
ListIterator<E>     listIterator(int location) //迭代器,從location起始
ListIterator<E>     listIterator() //迭代器
E                   remove(int location) //刪除location位置的元素
E                   set(int location, E object) //重置location位置的元素爲object
List<E>             subList(int start, int end) //獲取[start, end)之間的元素
// ArrayList新增的API
Object               clone() //複製元素
void                 ensureCapacity(int minimumCapacity) //最低容量
void                 trimToSize() //修剪數組大小爲當前元素個數
void                 removeRange(int fromIndex, int toIndex) //刪除[fromIndex, toIndex)之間的元素

1.2 使用示例

package com;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Main {

    public static void main(String[] args) {
   // write your code here
        List list = new ArrayList<>(20); //申請一個初始容量爲20的ArrayList
        String element; //要填充的元素
        for (int i = 0; i < 10; i++) {
            element = "num-" + i;
            list.add(element); // 填充list
        }
        list.add(10, "num-10"); //在指定位置增加元素

        //使用Iterator遍歷list
        for (Iterator iter = list.iterator(); iter.hasNext();) {
            System.out.print(iter.next() + " ");
        }
        System.out.println(" ");

        System.out.println("The second element is: " + list.get(1)); //獲取第2個元素
        System.out.println("array size is: " + list.size()); //獲取list大小
        System.out.println("is array list contains num-15:" + list.contains("num-15")); //判斷list是否含有num-15
        list.set(2,"num-3-1"); //將第三個元素設置爲num-3-1

        String[] arr = (String[])list.toArray(new String[0]); //將ArrayList轉換爲數組
        for (String str:arr) { //遍歷數組
            System.out.print(str + " ");
        }
    }
}

  運行結果如下:

num-0 num-1 num-2 num-3 num-4 num-5 num-6 num-7 num-8 num-9 num-10
The second element is: num-1
array size is: 11
is array list contains num-15:false
num-0 num-1 num-3-1 num-3 num-4 num-5 num-6 num-7 num-8 num-9 num-10

2 源碼分析

2.1構造函數

  ArrayList有三個構造函數,提供三種創建ArrayList實例的方法。

/**
 * 獲取一個初始長度爲initialCapacity的空ArrayList
 * @param initialCapacity
 */
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);
    }
}

/**
 * 返回一個空ArrayList
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

/**
 * 返回一個用ArrayList,並且用集合c進行初始化
 * @param c
 */
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;
    }
}

2.2 add方法

/**
 * 增加元素
 * @param e
 * @return
 */
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // 確定ArrayList長度
    elementData[size++] = e; //向數組中增加元素
    return true;
}

2.3 remove方法

/**
 * 刪除元素
 * @param index
 * @return
 */
public E remove(int index) {
    rangeCheck(index); //檢查下標是否合法

    modCount++;
    E oldValue = elementData(index); //獲取刪除的元素

    int numMoved = size - index - 1;
    if (numMoved > 0) //移動元素
        System.arraycopy(elementData, index+1, elementData, index,
                numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

2.4 toArray方法

  toArray有兩個重載方法,一個不帶參數返回Object數字,另一個帶參數,返回任意類型的數組。

/**
 * 返回Object對象的數組
 * @return
 */
public Object[] toArray() {
    return Arrays.copyOf(elementData, size);
}

/**
 * 返回任意對象類型的數組
 * @param a
 * @param <T>
 * @return
 */
public <T> T[] toArray(T[] a) {
    if (a.length < size) //傳入數組大小小於size時,直接返回一個新數組
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size); //傳入數組大小大於size,將ArrayList中的內容複製到數組中
    if (a.length > size)
        a[size] = null;
    return a;
}

參考:

[1] http://www.cnblogs.com/skywang12345/p/3308556.html
[2] http://blog.chinaunix.net/uid-29702073-id-4334609.html
[3]http://www.cnblogs.com/hzmark/archive/2012/12/20/ArrayList.html

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