List接口中,重要的兩個實現是ArrayList和LinkedList,其中ArrayList又比LinkedList經常使用。這是由於ArrayList的讀取性能遠遠高於LinkedList。本篇博文將介紹ArrayList,稍後介紹LinkedList及其二者的區別。java
Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the List interface,this class provides methods to manipulate the size of the array that is used internally to store the list.
ArrayList是實現了List接口的、大小可變的數組隊列。可以實現全部List接口的可選操做,並容許包括 null 在內的全部元素。除了實現 List 接口外,此類還提供一些方法來存儲列表的數組的大小。(此類大體上等同於 Vector 類,除了此類是不一樣步的。)--JDK API翻譯(可能不是很精確,請諒解)算法
從API的定義中能夠看出,ArrayList是一個數組隊列,至關於動態數組。與數組相比,可以動態增加。api
java.util 類 ArrayList<E> java.lang.Object - java.util.AbstractCollection<E> - java.util.AbstractList<E> - java.util.ArrayList<E> 全部已實現的接口: Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
ArrayList繼承了AbstractList,實現了List,它是一個數組隊列,提供了相關的增、改、刪數組
查等功能。安全
ArrayList實現了RandomAccess接口,提供了隨機訪問功能。RandomAccess是List 實現所使用的標記接口,用來代表其支持快速(一般是固定時間)隨機訪問。此接口的主要目的是容許通常的算法更改其行爲,從而在將其應用到隨機或連續訪問列表時能提供良好的性能。(來自JDk API翻譯)數據結構
ArrayList實現了Cloneable接口,提供了克隆功能多線程
ArrayList實現了java.io.Serializable藉口,這意味着ArrayList支持序列化。併發
注意:ArrayList是非線程安全的!因此,建議在多線程程序中避免使用ArrayList,可使用Vector或者CopyOnWriteArrayList。(這兩個類的用法及其實現,在稍後的博文中將被介紹)app
package java.util; public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { //序列版本號 private static final long serialVersionUID = 8683452581122892189L; /** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. * 數組緩衝區中的數組的元素存儲,即保存ArrayList中數據的數組 */ private transient Object[] elementData; /** * The size of the ArrayList (the number of elements it contains). * ArrayList中實際數據的數量 * @serial */ private int size; }
從源碼中看到ArrayList有2個重要對象dom
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { /** * Constructs an empty list with the specified initial capacity. * * 構造一個具備指定初始容量的空列表。 */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); //新建一個數組,大小爲入參值 this.elementData = new Object[initialCapacity]; } /** * Constructs an empty list with an initial capacity of ten. * ArrayList的無參構造器, 構造一個初始容量爲 10 的空列表 */ public ArrayList() { this(10); } /** * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * 構造一個包含指定 collection 的元素的列表,這些元素是按照該 collection 的迭代器返回它們的順序排列的。 */ public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) //Arrays.copyOf方法:數組複製 elementData = Arrays.copyOf(elementData, size, Object[].class); } }
當ArrayList容量不足以容納所有元素時,ArrayList會從新設置容量:新的容量 = (原始容量 X 3) / 2 + 1。再次說明在添加大量元素前,應用程序應該使用 ensureCapacity 操做來增長 ArrayList 實例的容量。以減小遞增式再分配的數量。
/** * Increases the capacity of this <tt>ArrayList</tt> instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * 增長此 ArrayList 實例的容量,以確保它至少可以容納最小容量參數所指定的元素數。 */ public void ensureCapacity(int minCapacity) { //將修改統計計數 +1 modCount++; int oldCapacity = elementData.length; //若是傳入最小容量大於原來數組的長度,就增長arrayList容量 //新的容量 = (原始容量 * 3)/2 + 1 if (minCapacity > oldCapacity) { Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } }
將此 ArrayList 實例的容量調整爲列表的當前大小。應用程序可使用此操做來最小化 ArrayList 實例的存儲量。
/** * Trims the capacity of this ArrayList instance to be the list's current size. * 將此 ArrayList 實例的容量調整爲列表的當前大小,也即將當前容量值設置爲實際元素個數 */ public void trimToSize() { modCount++; int oldCapacity = elementData.length; if (size < oldCapacity) { elementData = Arrays.copyOf(elementData, size); } }
將指定的元素添加到此列表的尾部。在調整數組大小以前要判斷是否須要調整arrayList容量
/** * Appends the specified element to the end of this list. * * 添加元素e */ public boolean add(E e) { //肯定ArrayList容量大小 ensureCapacity(size + 1); // Increments modCount!! //添加e到ArrayList尾部 elementData[size++] = e; return true; }
/** * Returns true if this list contains the specified element. * 返回ArrayList是否包含Object(o) */ public boolean contains(Object o) { return indexOf(o) >= 0; } /** * Returns the index of the first occurrence of the specified element * in this list, or -1 if this list does not contain the element. * 正向查找,返回元素的索引值,若是元素不存在集合中,就返回-1 */ public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }
package java.util; public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { // 正向查找,返回元素的索引值 public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; } // 反向查找,返回元素的索引值 public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; } // 反向查找(從數組末尾向開始查找),返回元素(o)的索引值 public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; } // 返回ArrayList的Object數組 public Object[] toArray() { return Arrays.copyOf(elementData, size); } // 返回ArrayList的模板數組。所謂模板數組,便可以將T設爲任意的數據類型 public <T> T[] toArray(T[] a) { // 若數組a的大小 < ArrayList的元素個數; // 則新建一個T[]數組,數組大小是「ArrayList的元素個數」,並將「ArrayList」所有拷貝到新數組中 if (a.length < size) return (T[]) Arrays.copyOf(elementData, size, a.getClass()); // 若數組a的大小 >= ArrayList的元素個數; // 則將ArrayList的所有元素都拷貝到數組a中。 System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } // 設置index位置的值爲element public E set(int index, E element) { RangeCheck(index); E oldValue = (E) elementData[index]; elementData[index] = element; return oldValue; } // 將e添加到ArrayList的指定位置 public void add(int index, E element) { if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); ensureCapacity(size+1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } // 刪除ArrayList指定位置的元素 public E remove(int index) { RangeCheck(index); modCount++; E oldValue = (E) elementData[index]; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work return oldValue; } // 刪除ArrayList的指定元素 public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } // 快速刪除第index個元素 private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; // 從"index+1"開始,用後面的元素替換前面的元素。 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); // 將最後一個元素設爲null elementData[--size] = null; // Let gc do its work } // 刪除元素 public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { // 便利ArrayList,找到「元素o」,則刪除,並返回true。 for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } // 清空ArrayList,將所有的元素設爲null public void clear() { modCount++; for (int i = 0; i < size; i++) elementData[i] = null; size = 0; } // 將集合c追加到ArrayList中 public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacity(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } // 從index位置開始,將集合c添加到ArrayList public boolean addAll(int index, Collection<? extends E> c) { if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size); Object[] a = c.toArray(); int numNew = a.length; ensureCapacity(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; } // 刪除fromIndex到toIndex之間的所有元素。 protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // Let gc do its work int newSize = size - (toIndex-fromIndex); while (size != newSize) elementData[--size] = null; } // 克隆函數 public Object clone() { try { ArrayList<E> v = (ArrayList<E>) super.clone(); // 將當前ArrayList的所有元素拷貝到v中 v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } } }
集合操做中最多見的就是遍歷操做了,ArrayList支持3種遍歷方式:迭代器遍歷、隨機訪問和for循環|(foreach循環)
Integer value = null; Iterator iter = list.iterator(); while (iter.hasNext()) { value = (Integer)iter.next(); }
Integer value = null; int size = list.size(); for (int i=0; i<size; i++) { value = (Integer)list.get(i); }
Integer value = null; for (Integer integ:list) { value = integ; }
package com.my.mobile; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class TestArrayList { public static void main(String[] args) { TestArrayList t = new TestArrayList(); List<Data> initArrayList = t.initArrayList(100000); testiterator(initArrayList); testRandomAccess(initArrayList); testforeach(initArrayList); } /** * 測試foreach循環遍歷ArrayList性能 * @param initArrayList * */ private static void testforeach(List<Data> initArrayList) { // TODO Auto-generated method stub long starttime = System.currentTimeMillis(); for (Data data : initArrayList) { // System.out.println(data.toString()); } System.out.println("foreach遍歷完畢,耗時["+(System.currentTimeMillis() - starttime)+"]ms"); } private static void testRandomAccess(List<Data> initArrayList) { // TODO Auto-generated method stub long starttime = System.currentTimeMillis(); for(int i = 0;i<initArrayList.size();i++){ Data data = initArrayList.get(i); // System.out.println(data.toString()); } System.out.println("randomAccess遍歷完畢,耗時["+(System.currentTimeMillis() - starttime)+"]ms"); } private static void testiterator(List<Data> initArrayList) { // TODO Auto-generated method stub long starttime = System.currentTimeMillis(); for(Iterator<Data> iter = initArrayList.iterator();iter.hasNext();){ Data data = iter.next(); // System.out.println(data.toString()); } System.out.println("iterator遍歷完畢,耗時["+(System.currentTimeMillis() - starttime)+"]ms"); } private List<Data> initArrayList(int listSize){ Data data = new Data(); List<Data> arrayList = new ArrayList<Data>(); for(int i = 0;i<listSize;i++){ try { TestArrayList.Data data_clone = data.clone(); data_clone.setId(i+""); data_clone.setName("我是第"+i+"個酷酷的酷"); data_clone.setUser("kucs"); arrayList.add(data_clone); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return arrayList; } class Data implements Cloneable{ private String id; private String name; private String user; public Data() { super(); // TODO Auto-generated constructor stub } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } @Override public String toString() { return "Data [id=" + id + ", name=" + name + ", user=" + user + "]"; } @Override protected Data clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return (Data)super.clone(); } } }
運行結果:
iterator遍歷完畢,耗時[34]ms randomAccess遍歷完畢,耗時[12]ms foreach遍歷完畢,耗時[14]ms
經此實驗,遍歷ArrayList時,使用隨機訪問,遍歷比較快。