1、開始 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable 繼承了抽象類AbstractList,實現了List接口,RandomAccess接口(數據隨機存儲),Cloneable接口(可克隆),Serializable接口(可序列化) 2、屬性 //用於存放元素的數組,不可進行序列化 private transient Object[] elementData; //已經存放的元素的個數 private int size; 3、構造器 //指定列表大小 public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); this.elementData = new Object[initialCapacity]; } //默認列表大小爲10 public ArrayList() { this(10); } //有初始內容的列表 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) elementData = Arrays.copyOf(elementData, size, Object[].class); } 4、方法 1)、添加 //向列表中添加元素,返回是否添加成功 public boolean add(E e) { //是否擴容 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } //向列表中指定的位置添加元素,其餘的元素後移 public void add(int index, E element) { //檢測下標是否合法,下標範圍[0,size] rangeCheckForAdd(index); //是否擴容 ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } 2)、獲取和設置 //根據下標返回元素 E elementData(int index) { return (E) elementData[index]; } //根據下標獲取元素 public E get(int index) { //檢測下標是否合法,下標範圍[0,size) rangeCheck(index); return elementData(index); } //設置列表中指定位置中的元素,並返回該位置的舊數據 public E set(int index, E element) { //檢測下標是否合法,下標範圍[0,size) rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } 3)、刪除 //刪除指定位置的元素,並返回要刪除的元素 public E remove(int index) { //檢測下標是否合法,下標範圍[0,size) 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; // Let gc do its work return oldValue; } //刪除指定的元素,返回是否刪除成功,分爲刪除的元素是否爲null,以後分別進行遍歷刪除 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; } //快速刪除 /* * Private remove method that skips bounds checking and does not * return the value removed. */ private void fastRemove(int index) { //記錄更改的次數 modCount++; //須要移動的元素個數 int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); //利於GC elementData[--size] = null; // Let gc do its work } 4)、擴容檢測 //目標容量與當前容量進行比較,是否進行擴容 private void ensureCapacityInternal(int minCapacity) { //擴容至關於一次更改 modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } /** * The maximum size of array to allocate. * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //擴容,在原來的基礎上增長0.5,即容量是原來的1.5倍 private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); //通常擴容與目標容量進行比較 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //獲取最大的容量 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } //獲取最大的列表容量 private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } 5)、範圍檢測 //下標範圍[0,size) /** * Checks if the given index is in range. If not, throws an appropriate * runtime exception. This method does *not* check if the index is * negative: It is always used immediately prior to an array access, * which throws an ArrayIndexOutOfBoundsException if index is negative. */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } //下標範圍[0,size],用於add(index)與addAll方法 /** * A version of rangeCheck used by add and addAll. */ private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * Constructs an IndexOutOfBoundsException detail message. * Of the many possible refactorings of the error handling code, * this "outlining" performs best with both server and client VMs. */ private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size; } 6)、獲取集合間的交集和差集 //集合差集 public boolean removeAll(Collection<?> c) { return batchRemove(c, false); } //集合交集 public boolean retainAll(Collection<?> c) { return batchRemove(c, true); } //集合間的操做 private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; } 7)、將集合添加到列表中 //將集合添加到列表末尾 public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } //將集合添加到列表中指定的位置 public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(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; } 8)、基礎方法 //獲取列表元素個數 public int size() { return size; } //列表是否爲空,即大小是否爲0 public boolean isEmpty() { return size == 0; } //列表是否包含該元素 public boolean contains(Object o) { return indexOf(o) >= 0; } //查找元素在列表中第一次出現的位置,循環遍歷 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; } //將列表轉換爲數組 public Object[] toArray() { return Arrays.copyOf(elementData, size); } //將列表轉換給指定的數組 @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < 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); if (a.length > size) a[size] = null; return a; } //縮減列表中不存在的元素 public void trimToSize() { modCount++; int oldCapacity = elementData.length; if (size < oldCapacity) { elementData = Arrays.copyOf(elementData, size); } } 9)、迭代器,都支持fail-fast機制,可能會拋出ConcurrentModificationException異常 //列表迭代器 public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); } //列表迭代器 public ListIterator<E> listIterator() { return new ListItr(0); } //迭代器 public Iterator<E> iterator() { return new Itr(); } //迭代器定義 private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; //是否還有元素 public boolean hasNext() { return cursor != size; } //獲取下一個元素 @SuppressWarnings("unchecked") public E next() { checkForComodification(); //當前元素下標 int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); //下一個元素的下標 cursor = i + 1; //指定當前最後一個下標 return (E) elementData[lastRet = i]; } //刪除當前最後一個元素,並指定當前位置的下標 public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { //刪除元素 ArrayList.this.remove(lastRet); //指定當前下標 cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
//列表迭代器定義 private class ListItr extends Itr implements ListIterator<E> { ListItr(int index) { super(); cursor = index; } //是否有前一個 public boolean hasPrevious() { return cursor != 0; } //獲取下一個索引 public int nextIndex() { return cursor; } //獲取前一個索引 public int previousIndex() { return cursor - 1; } //獲取前一個元素 @SuppressWarnings("unchecked") public E previous() { checkForComodification(); int i = cursor - 1; if (i < 0) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i; return (E) elementData[lastRet = i]; } //設置元素 public void set(E e) { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(lastRet, e); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } //添加元素 public void add(E e) { checkForComodification(); try { int i = cursor; ArrayList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } }
10)、子列表,更改子列表時,會影響到父列表,但更改父列表時,子列表將拋出異常ConcurrentModificationException //獲取子列表 public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); } //子列表檢測 static void subListRangeCheck(int fromIndex, int toIndex, int size) { if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); if (toIndex > size) throw new IndexOutOfBoundsException("toIndex = " + toIndex); if (fromIndex > toIndex) throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); } //如下是子列表對象中的方法 //子列表構造器 SubList(AbstractList<E> parent, int offset, int fromIndex, int toIndex) { this.parent = parent;//父列表對象 this.parentOffset = fromIndex; this.offset = offset + fromIndex; this.size = toIndex - fromIndex;//子列表大小 this.modCount = ArrayList.this.modCount; //子列表更改記錄,必須跟父列表保持同步,不然拋出異常ConcurrentModificationException } //往指定位置添加元素 public void add(int index, E e) { rangeCheckForAdd(index); checkForComodification(); //往父列表中添加元素後,須要將更改記錄同步到子列表中 parent.add(parentOffset + index, e); this.modCount = parent.modCount; this.size++; } //刪除指定位置的元素 public E remove(int index) { rangeCheck(index); checkForComodification(); E result = parent.remove(parentOffset + index); //往父列表中刪除元素後,須要將更改記錄同步到子列表中 this.modCount = parent.modCount; this.size--; return result; } //檢測子列表與父列表的更改狀態是否一致 private void checkForComodification() { if (ArrayList.this.modCount != this.modCount) throw new ConcurrentModificationException(); }
ArrayList的遍歷方式 1)、根據索引值進行遍歷 2)、經過迭代器進行遍歷 3)、經過foreach ArrayList和LinkedList 1)、ArrayList是基於動態數組實現的數據結構,而LinkedList是基於鏈表實現的數據結構 2)、對於隨機訪問get和set,ArrayList優於LinkedList,這是因爲LinkedList須要移動指針 3)、對於新增和刪除操做add和remove,LinkedList比較佔優點,這是因爲ArrayList須要移動數據 ArrayList和Vector 1)、Vector和ArrayList實現幾乎同樣,惟一不一樣的是Vector是同步類(synchronized),故開銷比ArrayList大,訪問慢 2)、Vector每次擴容後其大小是原來的2倍,而ArrayList是1.5倍 3)、Vector還有一個子類Stack
參考資料:php
http://www.importnew.com/17440.htmlhtml
http://anxpp.com/index.php/archives/664/java