1 public interface Collection<E> extends Iterable<E> { 2 int size(); 3 boolean isEmpty(); 4 boolean contains(Object o); 5 Iterator<E> iterator(); 6 Object[] toArray(); 7 <T> T[] toArray(T[] a); 8 boolean add(E e); 9 boolean remove(Object o); 10 boolean containsAll(Collection<?> c); 11 boolean addAll(Collection<? extends E> c); 12 boolean removeAll(Collection<?> c); 13 boolean retainAll(Collection<?> c); 14 void clear(); 15 boolean equals(Object o); 16 int hashCode(); 17 }
1 public interface List<E> extends Collection<E> { 2 int size(); 3 boolean isEmpty(); 4 boolean contains(Object o); 5 Iterator<E> iterator(); 6 Object[] toArray(); 7 <T> T[] toArray(T[] a); 8 boolean add(E e); 9 boolean remove(Object o); 10 boolean containsAll(Collection<?> c); 11 boolean addAll(Collection<? extends E> c); 12 boolean addAll( int index, Collection<? extends E> c); 13 boolean removeAll(Collection<?> c); 14 boolean retainAll(Collection<?> c); 15 void clear(); 16 boolean equals(Object o); 17 int hashCode(); 18 E get( int index); 19 E set( int index, E element); 20 void add( int index, E element); 21 E remove( int index); 22 int indexOf(Object o); 23 int lastIndexOf(Object o); 24 ListIterator<E> listIterator(); 25 ListIterator<E> listIterator( int index); 26 List<E> subList( int fromIndex, int toIndex); 27 }
1 private transient Object[] elementData; 2 private int size;
能夠看到用一個Object數組來存儲數據,用一個int值來計數,記錄當前容器的數據大小。html
1 /** 2 * Save the state of the <tt>ArrayList</tt> instance to a stream (that 3 * is, serialize it). 4 * 5 * @serialData The length of the array backing the <tt>ArrayList </tt> 6 * instance is emitted (int), followed by all of its elements 7 * (each an <tt>Object</tt> ) in the proper order. 8 */ 9 private void writeObject(java.io.ObjectOutputStream s) 10 throws java.io.IOException{ 11 // Write out element count, and any hidden stuff 12 int expectedModCount = modCount ; 13 s.defaultWriteObject(); 14 15 // Write out array length 16 s.writeInt( elementData.length ); 17 18 // Write out all elements in the proper order. 19 for (int i=0; i<size; i++) 20 s.writeObject( elementData[i]); 21 22 if (modCount != expectedModCount) { 23 throw new ConcurrentModificationException(); 24 } 25 26 } 27 28 /** 29 * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is, 30 * deserialize it). 31 */ 32 private void readObject(java.io.ObjectInputStream s) 33 throws java.io.IOException, ClassNotFoundException { 34 // Read in size, and any hidden stuff 35 s.defaultReadObject(); 36 37 // Read in array length and allocate array 38 int arrayLength = s.readInt(); 39 Object[] a = elementData = new Object[arrayLength]; 40 41 // Read in all elements in the proper order. 42 for (int i=0; i<size; i++) 43 a[i] = s.readObject(); 44 }
英語註釋很詳細,也很容易讀懂,就不進行翻譯了。那麼想一下爲何要這樣設計呢,豈不是很麻煩。下面簡單進行解釋下:java
1 /** 2 * 構造一個具備指定容量的list 3 */ 4 public ArrayList( int initialCapacity) { 5 super(); 6 if (initialCapacity < 0) 7 throw new IllegalArgumentException( "Illegal Capacity: " + 8 initialCapacity); 9 this.elementData = new Object[initialCapacity]; 10 } 11 12 /** 13 * 構造一個初始容量爲10的list 14 */ 15 public ArrayList() { 16 this(10); 17 } 18 19 /** 20 * 構造一個包含指定元素的list,這些元素的是按照Collection的迭代器返回的順序排列的 21 */ 22 public ArrayList(Collection<? extends E> c) { 23 elementData = c.toArray(); 24 size = elementData .length; 25 // c.toArray might (incorrectly) not return Object[] (see 6260652) 26 if (elementData .getClass() != Object[].class) 27 elementData = Arrays.copyOf( elementData, size , Object[].class); 28 }
1 /** 2 * 添加一個元素 3 */ 4 public boolean add(E e) { 5 // 進行擴容檢查 6 ensureCapacity( size + 1); // Increments modCount 7 // 將e增長至list的數據尾部,容量+1 8 elementData[size ++] = e; 9 return true; 10 } 11 12 /** 13 * 在指定位置添加一個元素 14 */ 15 public void add(int index, E element) { 16 // 判斷索引是否越界,這裏會拋出多麼熟悉的異常。。。 17 if (index > size || index < 0) 18 throw new IndexOutOfBoundsException( 19 "Index: "+index+", Size: " +size); 20 21 // 進行擴容檢查 22 ensureCapacity( size+1); // Increments modCount 23 // 對數組進行復制處理,目的就是空出index的位置插入element,並將index後的元素位移一個位置 24 System. arraycopy(elementData, index, elementData, index + 1, 25 size - index); 26 // 將指定的index位置賦值爲element 27 elementData[index] = element; 28 // list容量+1 29 size++; 30 } 31 /** 32 * 增長一個集合元素 33 */ 34 public boolean addAll(Collection<? extends E> c) { 35 //將c轉換爲數組 36 Object[] a = c.toArray(); 37 int numNew = a.length ; 38 //擴容檢查 39 ensureCapacity( size + numNew); // Increments modCount 40 //將c添加至list的數據尾部 41 System. arraycopy(a, 0, elementData, size, numNew); 42 //更新當前容器大小 43 size += numNew; 44 return numNew != 0; 45 } 46 /** 47 * 在指定位置,增長一個集合元素 48 */ 49 public boolean addAll(int index, Collection<? extends E> c) { 50 if (index > size || index < 0) 51 throw new IndexOutOfBoundsException( 52 "Index: " + index + ", Size: " + size); 53 54 Object[] a = c.toArray(); 55 int numNew = a.length ; 56 ensureCapacity( size + numNew); // Increments modCount 57 58 // 計算須要移動的長度(index以後的元素個數) 59 int numMoved = size - index; 60 // 數組複製,空出第index到index+numNum的位置,即將數組index後的元素向右移動numNum個位置 61 if (numMoved > 0) 62 System. arraycopy(elementData, index, elementData, index + numNew, 63 numMoved); 64 65 // 將要插入的集合元素複製到數組空出的位置中 66 System. arraycopy(a, 0, elementData, index, numNew); 67 size += numNew; 68 return numNew != 0; 69 } 70 71 /** 72 * 數組容量檢查,不夠時則進行擴容 73 */ 74 public void ensureCapacity( int minCapacity) { 75 modCount++; 76 // 當前數組的長度 77 int oldCapacity = elementData .length; 78 // 最小須要的容量大於當前數組的長度則進行擴容 79 if (minCapacity > oldCapacity) { 80 Object oldData[] = elementData; 81 // 新擴容的數組長度爲舊容量的1.5倍+1 82 int newCapacity = (oldCapacity * 3)/2 + 1; 83 // 若是新擴容的數組長度仍是比最小須要的容量小,則以最小須要的容量爲長度進行擴容 84 if (newCapacity < minCapacity) 85 newCapacity = minCapacity; 86 // minCapacity is usually close to size, so this is a win: 87 // 進行數據拷貝,Arrays.copyOf底層實現是System.arrayCopy() 88 elementData = Arrays.copyOf( elementData, newCapacity); 89 } 90 }
1 /** 2 * 根據索引位置刪除元素 3 */ 4 public E remove( int index) { 5 // 數組越界檢查 6 RangeCheck(index); 7 8 modCount++; 9 // 取出要刪除位置的元素,供返回使用 10 E oldValue = (E) elementData[index]; 11 // 計算數組要複製的數量 12 int numMoved = size - index - 1; 13 // 數組複製,就是將index以後的元素往前移動一個位置 14 if (numMoved > 0) 15 System. arraycopy(elementData, index+1, elementData, index, 16 numMoved); 17 // 將數組最後一個元素置空(由於刪除了一個元素,而後index後面的元素都向前移動了,因此最後一個就沒用了),好讓gc儘快回收 18 // 不要忘了size減一 19 elementData[--size ] = null; // Let gc do its work 20 21 return oldValue; 22 } 23 24 /** 25 * 根據元素內容刪除,只刪除匹配的第一個 26 */ 27 public boolean remove(Object o) { 28 // 對要刪除的元素進行null判斷 29 // 對數據元素進行遍歷查找,知道找到第一個要刪除的元素,刪除後進行返回,若是要刪除的元素正好是最後一個那就慘了,時間複雜度可達O(n) 。。。 30 if (o == null) { 31 for (int index = 0; index < size; index++) 32 // null值要用==比較 33 if (elementData [index] == null) { 34 fastRemove(index); 35 return true; 36 } 37 } else { 38 for (int index = 0; index < size; index++) 39 // 非null固然是用equals比較了 40 if (o.equals(elementData [index])) { 41 fastRemove(index); 42 return true; 43 } 44 } 45 return false; 46 } 47 48 /* 49 * Private remove method that skips bounds checking and does not 50 * return the value removed. 51 */ 52 private void fastRemove(int index) { 53 modCount++; 54 // 原理和以前的add同樣,仍是進行數組複製,將index後的元素向前移動一個位置,不細解釋了, 55 int numMoved = size - index - 1; 56 if (numMoved > 0) 57 System. arraycopy(elementData, index+1, elementData, index, 58 numMoved); 59 elementData[--size ] = null; // Let gc do its work 60 } 61 62 /** 63 * 數組越界檢查 64 */ 65 private void RangeCheck(int index) { 66 if (index >= size ) 67 throw new IndexOutOfBoundsException( 68 "Index: "+index+", Size: " +size); 69 }
PS:看到了這個方法,即可jdk源碼有些地方寫的也不是那麼精巧,好比這裏remove時將數組越界檢查封裝成了一個單獨方法,但是往前翻一下add方法中的數組越界就沒有進行封裝,須要檢查的時候都是寫一遍同樣的代碼,why啊。。。設計模式
1 /** 2 * 將底層數組的容量調整爲當前實際元素的大小,來釋放空間。 3 */ 4 public void trimToSize() { 5 modCount++; 6 // 當前數組的容量 7 int oldCapacity = elementData .length; 8 // 若是當前實際元素大小 小於 當前數組的容量,則進行縮容 9 if (size < oldCapacity) { 10 elementData = Arrays.copyOf( elementData, size ); 11 } 12
1 /** 2 * 將指定位置的元素更新爲新元素 3 */ 4 public E set( int index, E element) { 5 // 數組越界檢查 6 RangeCheck(index); 7 8 // 取出要更新位置的元素,供返回使用 9 E oldValue = (E) elementData[index]; 10 // 將該位置賦值爲行的元素 11 elementData[index] = element; 12 // 返回舊元素 13 return oldValue; 14 }
1 /** 2 * 查找指定位置上的元素 3 */ 4 public E get( int index) { 5 RangeCheck(index); 6 7 return (E) elementData [index]; 8 }
因爲ArrayList使用數組實現,更新和查找直接基於下標操做,變得十分簡單。數組
1 /** 2 * Returns <tt>true</tt> if this list contains the specified element. 3 * More formally, returns <tt>true</tt> if and only if this list contains 4 * at least one element <tt>e</tt> such that 5 * <tt>(o==null ? e==null : o.equals(e))</tt>. 6 * 7 * @param o element whose presence in this list is to be tested 8 * @return <tt> true</tt> if this list contains the specified element 9 */ 10 public boolean contains(Object o) { 11 return indexOf(o) >= 0; 12 } 13 14 /** 15 * Returns the index of the first occurrence of the specified element 16 * in this list, or -1 if this list does not contain the element. 17 * More formally, returns the lowest index <tt>i</tt> such that 18 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, 19 * or -1 if there is no such index. 20 */ 21 public int indexOf(Object o) { 22 if (o == null) { 23 for (int i = 0; i < size; i++) 24 if (elementData [i]==null) 25 return i; 26 } else { 27 for (int i = 0; i < size; i++) 28 if (o.equals(elementData [i])) 29 return i; 30 } 31 return -1; 32 } 33 34 /** 35 * Returns the index of the last occurrence of the specified element 36 * in this list, or -1 if this list does not contain the element. 37 * More formally, returns the highest index <tt>i</tt> such that 38 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, 39 * or -1 if there is no such index. 40 */ 41 public int lastIndexOf(Object o) { 42 if (o == null) { 43 for (int i = size-1; i >= 0; i--) 44 if (elementData [i]==null) 45 return i; 46 } else { 47 for (int i = size-1; i >= 0; i--) 48 if (o.equals(elementData [i])) 49 return i; 50 } 51 return -1; 52 }
1 /** 2 * Returns the number of elements in this list. 3 * 4 * @return the number of elements in this list 5 */ 6 public int size() { 7 return size ; 8 } 9 10 /** 11 * Returns <tt>true</tt> if this list contains no elements. 12 * 13 * @return <tt> true</tt> if this list contains no elements 14 */ 15 public boolean isEmpty() { 16 return size == 0; 17 }