首先,來看ArrayList的定義:java
1 public class ArrayList<E> extends AbstractList<E> 2 implements List<E>, RandomAccess, Cloneable, java.io.Serializable
ArrayList繼承於AbstractList類,並實現了List、RandomAccess、Cloneable和Serializable接口。數組
1 /** 2 * 定義ArrayList內部保存數據用的數組。 3 */ 4 private transient Object[] elementData; 5 6 /** 7 * 定義ArrayList的實際包含數據的長度。 8 */ 9 private int size;
看構造方法:app
1 /** 2 * 根據傳入的initialCapacity來定義一個數組。若是initialCapacity小於0,則拋出IllegalArgument異常。 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的Object類型數組。 14 */ 15 public ArrayList() { 16 this(10); 17 } 18 19 /** 20 * 根據傳入的集合來初始化。若是傳入的集合的toArray()方法返回的不是Object[]類型的,則利用Arrays.copyOf來轉爲Object[]類型 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 }
注意第3個構造方法當中有一個註釋:c.toArray might (incorrectly) not return Object[] (see 6260652),意識是說c.toArray不必定老是返回Object[]類型的數組,這是incorrectly的,你們能夠參照dom
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6260652來看看這個java的bug。this
下面開始分析ArrayList的各個方法:spa
①、trimToSize()code
1 /** 2 * 此方法將數組elementData中沒有用來存儲數據的內存釋放出來,減小佔用的內存空間。 3 * 使得list的size和capacity大小同樣。 4 */ 5 public void trimToSize() { 6 modCount++; 7 int oldCapacity = elementData.length; 8 if (size < oldCapacity) { 9 elementData = Arrays.copyOf(elementData, size); 10 } 11 }
②、ensureCapacity()blog
1 /** 2 * 數組擴容用的方法。若是傳入的minCapacity尚未之前的容量大,則什麼都不作;若是比之前的容量大,那也不必定就按照minCapacity的大小來擴容。 3 * 首先,將之前的容量擴大到1.5倍再加上1,若是擴大後的容量比minCapacity小,則容量最終仍是擴大到minCapacity,不然就擴大到之前的1.5倍加上1的大小。 4 * 也就是說,擴容至少擴大到之前的1.5倍再加上1。 5 */ 6 public void ensureCapacity(int minCapacity) { 7 modCount++; 8 int oldCapacity = elementData.length; 9 if (minCapacity > oldCapacity) { 10 Object oldData[] = elementData; 11 int newCapacity = (oldCapacity * 3)/2 + 1; 12 if (newCapacity < minCapacity) 13 newCapacity = minCapacity; 14 // minCapacity is usually close to size, so this is a win: 15 elementData = Arrays.copyOf(elementData, newCapacity); 16 } 17 }
③、size()和isEmpty()繼承
1 /** 2 * 返回list的大小,注意不是數組的容量大小。 3 */ 4 public int size() { 5 return size; 6 } 7 8 /** 9 * 根據list的大小是否爲0來判斷list是否爲空 10 */ 11 public boolean isEmpty() { 12 return size == 0; 13 }
④、indexOf()和lastIndexOf()接口
1 /** 2 * 從數組下標0開始查找o,找到的話就返回其下標,若是沒有找到,則返回-1。 3 */ 4 public int indexOf(Object o) { 5 if (o == null) { 6 for (int i = 0; i < size; i++) 7 if (elementData[i]==null) 8 return i; 9 } else { 10 for (int i = 0; i < size; i++) 11 if (o.equals(elementData[i])) 12 return i; 13 } 14 return -1; 15 } 16 17 /** 18 * 從數組最後一位開始向前查找o,找到的話返回其下標,不然返回-1。 19 */ 20 public int lastIndexOf(Object o) { 21 if (o == null) { 22 for (int i = size-1; i >= 0; i--) 23 if (elementData[i]==null) 24 return i; 25 } else { 26 for (int i = size-1; i >= 0; i--) 27 if (o.equals(elementData[i])) 28 return i; 29 } 30 return -1; 31 }
⑤、contains()
1 /** 2 * 調用indexOf方法來判斷o是否存在於list中。 3 */ 4 public boolean contains(Object o) { 5 return indexOf(o) >= 0; 6 }
⑥、clone()
1 /** 2 * 此方法爲淺層複製,不是深層複製 3 */ 4 public Object clone() { 5 try { 6 ArrayList<E> v = (ArrayList<E>) super.clone(); 7 v.elementData = Arrays.copyOf(elementData, size); 8 v.modCount = 0; 9 return v; 10 } catch (CloneNotSupportedException e) { 11 // this shouldn't happen, since we are Cloneable 12 throw new InternalError(); 13 } 14 }
⑦、toArray()和toArray(T[] a)
1 /** 2 * 將list轉爲數組,注意是從新建立了一個長度相同(爲size)的數組,與list內部的數組不是同一個 3 */ 4 public Object[] toArray() { 5 return Arrays.copyOf(elementData, size); 6 } 7 8 /** 9 * 將list轉爲數組,數組的類型由傳入的參數a決定。 10 * 若是a的長度小於list的長度,則從list的第一個元素開始直至填滿a; 11 * 若是a的長度大於list的長度,則把list的元素所有填入a後,將a[a.length]設爲null。 12 */ 13 public <T> T[] toArray(T[] a) { 14 if (a.length < size) 15 // Make a new array of a's runtime type, but my contents: 16 return (T[]) Arrays.copyOf(elementData, size, a.getClass()); 17 System.arraycopy(elementData, 0, a, 0, size); 18 if (a.length > size) 19 a[size] = null; 20 return a; 21 }
⑧、RangeCheck()
1 /** 2 * 此方法爲判斷index是否超出list的長度size,注意不是list的容量。 3 * 若是超出,則拋出IndexOutOfBounds異常。 4 * list的不少方法都會先調用此方法來作判斷。 5 */ 6 private void RangeCheck(int index) { 7 if (index >= size) 8 throw new IndexOutOfBoundsException( 9 "Index: "+index+", Size: "+size); 10 }
接下來的是一些訪問list的方法:
1 /** 2 * 首先調用RangeCheck方法判斷index合法性,而後直接返回數組對應下標的值。 3 */ 4 public E get(int index) { 5 RangeCheck(index); 6 7 return (E) elementData[index]; 8 } 9 10 /** 11 * 首先調用RangeCheck方法判斷index的合法性,而後定義一個變量oldValue指向數組對應下標的值, 12 * 再將此下標的值換爲傳入的參數element,最後返回舊的值oldValue。 13 */ 14 public E set(int index, E element) { 15 RangeCheck(index); 16 17 E oldValue = (E) elementData[index]; 18 elementData[index] = element; 19 return oldValue; 20 } 21 22 /** 23 * 此方法爲往list的下標爲size的地方添加元素e。 24 * 首先對數組進行擴容,而後將數組下標爲size的元素賦爲e。 25 */ 26 public boolean add(E e) { 27 ensureCapacity(size + 1); // Increments modCount!! 28 elementData[size++] = e; // 這種寫法一箭雙鵰,既賦了值,又把size加了1,能夠省下一行代碼。 29 return true; 30 } 31 32 /** 33 * 此方法爲在指定下標處添加元素。 34 * 首先判斷傳入的index是否合法,注意index能夠等於size,這時應該至關於前面的add(E e)方法。 35 * 而後也是先把數組擴容,接着經過System的arraycopy方法把數組從下表index開始到size-1處的元素總體日後移一位。 36 */ 37 public void add(int index, E element) { 38 if (index > size || index < 0) 39 throw new IndexOutOfBoundsException( 40 "Index: "+index+", Size: "+size); 41 42 ensureCapacity(size+1); // Increments modCount!! 43 System.arraycopy(elementData, index, elementData, index + 1, 44 size - index); 45 elementData[index] = element; 46 size++; 47 } 48 49 /** 50 * 此方法爲刪除指定下標處的元素。 51 * 首先判斷index的合法性。而後定義一個變量oldValue獲取數組指定下標處的元素。 52 * 而後定義numMoved變量獲取(size - index - 1)的值,若是爲0,則表示index爲list的最後一個元素的下標,那麼就木有必要再進行數組元素的移動了。 53 * 不然index不是最後一個元素的下標,那麼把數組裏的下標爲index+1的元素開始到最後一個元素所有往前移動一位。 54 * 再將list的最後一位賦值爲null,同時將size減小1。 55 * 最後返回oldValue,即被刪除的元素。 56 */ 57 public E remove(int index) { 58 RangeCheck(index); 59 60 modCount++; 61 E oldValue = (E) elementData[index]; 62 63 int numMoved = size - index - 1; 64 if (numMoved > 0) 65 System.arraycopy(elementData, index+1, elementData, index, 66 numMoved); 67 elementData[--size] = null; // Let gc do its work 68 69 return oldValue; 70 } 71 72 /** 73 * 刪除數組裏第一個值爲o的元素。 74 * 先判斷o是否爲null,若是是null,則遍歷數組,發現null的話,刪除null,並返回true; 75 * 若是不是null,則遍歷數組,調用o的equals方法一次和數組元素進行比較,若是爲true則刪除此元素並返回true。 76 */ 77 public boolean remove(Object o) { 78 if (o == null) { 79 for (int index = 0; index < size; index++) 80 if (elementData[index] == null) { 81 fastRemove(index); 82 return true; 83 } 84 } else { 85 for (int index = 0; index < size; index++) 86 if (o.equals(elementData[index])) { 87 fastRemove(index); 88 return true; 89 } 90 } 91 return false; 92 } 93 94 /* 95 * 私有的刪除方法,與remove方法有兩點區別:①不會返回被刪除的元素;②不會調用RangeCheck方法進行check。 96 */ 97 private void fastRemove(int index) { 98 modCount++; 99 int numMoved = size - index - 1; 100 if (numMoved > 0) 101 System.arraycopy(elementData, index+1, elementData, index, 102 numMoved); 103 elementData[--size] = null; // Let gc do its work 104 } 105 106 /** 107 * 此方法是清空list,遍歷數組,將裏面全部的元素都賦值爲null。同時,size也賦值爲0。 108 */ 109 public void clear() { 110 modCount++; 111 112 // Let gc do its work 113 for (int i = 0; i < size; i++) 114 elementData[i] = null; 115 116 size = 0; 117 } 118 119 /** 120 * Appends all of the elements in the specified collection to the end of 121 * this list, in the order that they are returned by the 122 * specified collection's Iterator. The behavior of this operation is 123 * undefined if the specified collection is modified while the operation 124 * is in progress. (This implies that the behavior of this call is 125 * undefined if the specified collection is this list, and this 126 * list is nonempty.) 127 * 128 * @param c collection containing elements to be added to this list 129 * @return <tt>true</tt> if this list changed as a result of the call 130 * @throws NullPointerException if the specified collection is null 131 */ 132 public boolean addAll(Collection<? extends E> c) { 133 Object[] a = c.toArray(); 134 int numNew = a.length; 135 ensureCapacity(size + numNew); // Increments modCount 136 System.arraycopy(a, 0, elementData, size, numNew); 137 size += numNew; 138 return numNew != 0; 139 } 140 141 /** 142 * 把此方法傳入的集合c依次從list的下標index開始添加,同時把原先下標index日後的全部元素再日後移動c.size()位。 143 */ 144 public boolean addAll(int index, Collection<? extends E> c) { 145 if (index > size || index < 0) 146 throw new IndexOutOfBoundsException( 147 "Index: " + index + ", Size: " + size); 148 149 Object[] a = c.toArray(); 150 int numNew = a.length; 151 ensureCapacity(size + numNew); // Increments modCount 152 153 int numMoved = size - index; 154 if (numMoved > 0) 155 System.arraycopy(elementData, index, elementData, index + numNew, 156 numMoved); 157 158 System.arraycopy(a, 0, elementData, index, numNew); 159 size += numNew; 160 return numNew != 0; 161 } 162 163 /** 164 * 刪除下標從fromIndex到toIndex-1的元素。 165 * 首先將下標從toIndex到size-1的元素所有向前移動size-toIndex位, 166 * 而後將list的後toIndex-fromIndex位的元素的值賦爲null。 167 */ 168 protected void removeRange(int fromIndex, int toIndex) { 169 modCount++; 170 int numMoved = size - toIndex; 171 System.arraycopy(elementData, toIndex, elementData, fromIndex, 172 numMoved); 173 174 // Let gc do its work 175 int newSize = size - (toIndex-fromIndex); 176 while (size != newSize) 177 elementData[--size] = null; 178 }
最後,還有兩個方法是序列化時處理用的:
1 /** 2 * 序列化時,先執行defaultWriteObject()方法;而後再把數組的長度也寫入流中,最後分別把數組中的每一個元素都寫到流中。 3 */ 4 private void writeObject(java.io.ObjectOutputStream s) 5 throws java.io.IOException{ 6 // Write out element count, and any hidden stuff 7 int expectedModCount = modCount; 8 s.defaultWriteObject(); 9 10 // Write out array length 11 s.writeInt(elementData.length); 12 13 // Write out all elements in the proper order. 14 for (int i=0; i<size; i++) 15 s.writeObject(elementData[i]); 16 17 if (modCount != expectedModCount) { 18 throw new ConcurrentModificationException(); 19 } 20 21 } 22 23 /** 24 * 從流中讀取元素,先調用defaultReadObject()方法,而後依次讀取數組長度,接着是數組當中的每一個元素信息。 25 * 和writeObject的寫入順序同樣。 26 */ 27 private void readObject(java.io.ObjectInputStream s) 28 throws java.io.IOException, ClassNotFoundException { 29 // Read in size, and any hidden stuff 30 s.defaultReadObject(); 31 32 // Read in array length and allocate array 33 int arrayLength = s.readInt(); 34 Object[] a = elementData = new Object[arrayLength]; 35 36 // Read in all elements in the proper order. 37 for (int i=0; i<size; i++) 38 a[i] = s.readObject(); 39 }
終於看完了,其實ArrayList的父類AbstractList中還有不少重要的實現,不過下回分解吧。