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
// 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源碼解析
總結:
(01) ArrayList 實際上是通過一個數組去保存數據的。當我們構造ArrayList時;若使用默認構造函數,則ArrayList的默認容量大小是10。
(02) 當ArrayList容量不足以容納全部元素時,ArrayList會重新設置容量:新的容量=“(原始容量x3)/2 + 1”。
(03) ArrayList的克隆函數,即是將全部元素克隆到一個數組中。
(04) ArrayList實現java.io.Serializable的方式。當寫入到輸出流時,先寫入“容量”,再依次寫入“每一個元素”;當讀出輸入流時,先讀取“容量”,再依次讀取“每一個元素”。
4 ArrayList遍歷方式
ArrayList支持的3種遍歷方式
(01) 第一種,通過迭代器遍歷。即通過Iterator去遍歷。
Integer value = null; Iterator iter = list.iterator(); while (iter.hasNext()) { value = (Integer)iter.next(); }
(02) 第二種,隨機訪問,通過索引值去遍歷。
由於ArrayList實現了RandomAccess接口,它支持通過索引值去隨機訪問元素。
Integer value = null; int size = list.size(); for (int i=0; i<size; i++) { value = (Integer)list.get(i); }
(03) 第三種,for循環遍歷。如下:
Integer value = null; for (Integer integ:list) { value = integ; }
下面通過一個實例,比較這3種方式的效率,實例代碼(ArrayListRandomAccessTest.java)如下:

import java.util.*; import java.util.concurrent.*; /* * @desc ArrayList遍歷方式和效率的測試程序。 * * @author skywang */ public class ArrayListRandomAccessTest { public static void main(String[] args) { List list = new ArrayList(); for (int i=0; i<100000; i++) list.add(i); //isRandomAccessSupported(list); iteratorThroughRandomAccess(list) ; iteratorThroughIterator(list) ; iteratorThroughFor2(list) ; } private static void isRandomAccessSupported(List list) { if (list instanceof RandomAccess) { System.out.println("RandomAccess implemented!"); } else { System.out.println("RandomAccess not implemented!"); } } public static void iteratorThroughRandomAccess(List list) { long startTime; long endTime; startTime = System.currentTimeMillis(); for (int i=0; i<list.size(); i++) { list.get(i); } endTime = System.currentTimeMillis(); long interval = endTime - startTime; System.out.println("iteratorThroughRandomAccess:" + interval+" ms"); } public static void iteratorThroughIterator(List list) { long startTime; long endTime; startTime = System.currentTimeMillis(); for(Iterator iter = list.iterator(); iter.hasNext(); ) { iter.next(); } endTime = System.currentTimeMillis(); long interval = endTime - startTime; System.out.println("iteratorThroughIterator:" + interval+" ms"); } public static void iteratorThroughFor2(List list) { long startTime; long endTime; startTime = System.currentTimeMillis(); for(Object obj:list) ; endTime = System.currentTimeMillis(); long interval = endTime - startTime; System.out.println("iteratorThroughFor2:" + interval+" ms"); } }
運行結果:
iteratorThroughRandomAccess:3 ms
iteratorThroughIterator:8 ms
iteratorThroughFor2:5 ms
由此可見,遍歷ArrayList時,使用隨機訪問(即,通過索引序號訪問)效率最高,而使用迭代器的效率最低!
5 toArray異常
6 ArrayList實例
本文通過一個實例(ArrayListTest.java),介紹 ArrayList 中常用API的用法。

import java.util.*; /* * @desc ArrayList常用API的測試程序 * @author skywang * @email kuiwu-wang@163.com */ public class ArrayListTest { public static void main(String[] args) { // 創建ArrayList ArrayList list = new ArrayList(); // 將“” list.add("1"); list.add("2"); list.add("3"); list.add("4"); // 將下面的元素添加到第1個位置 list.add(0, "5"); // 獲取第1個元素 System.out.println("the first element is: "+ list.get(0)); // 刪除“3” list.remove("3"); // 獲取ArrayList的大小 System.out.println("Arraylist size=: "+ list.size()); // 判斷list中是否包含"3" System.out.println("ArrayList contains 3 is: "+ list.contains(3)); // 設置第2個元素為10 list.set(1, "10"); // 通過Iterator遍歷ArrayList for(Iterator iter = list.iterator(); iter.hasNext(); ) { System.out.println("next is: "+ iter.next()); } // 將ArrayList轉換為數組 String[] arr = (String[])list.toArray(new String[0]); for (String str:arr) System.out.println("str: "+ str); // 清空ArrayList list.clear(); // 判斷ArrayList是否為空 System.out.println("ArrayList is empty: "+ list.isEmpty()); } }
本文來自http://www.cnblogs.com/skywang12345/p/3308556.html