在我們剛學Java時老師一定會說ArrayList是很好用的變長數組,你只要儘管插入刪除就可以了,比C++的數組控制簡單多了,
ArrayList是典型的自增長數組。
private int size; //數組中實際元素的數量
capacity表示數組的總大小,比如arr = new int[5],則capacity=5.
//initialCapacity為初始的數組大小,因為自增長數組的缺點就是重新分配數組時會耗費記憶體,
重新分配就意味著原空間的垃圾產生加重記憶體回收的負擔,
因此如果一開始分配的大一點,以後就會避免重新分配的次數
比如你如果要插入200個元素,則:
(1)一開始就分配200個元素的capacity,則一次分配
(2)一開始分配1個,不夠了再多分配1個,如果沒有記憶體回收,則1+2+3+......200=20100個空間
200和20100,差別很大吧。
先回顧下ArrayList中最核心的兩個語句:
int[]newarr = Arrays.copyOf(int[]old,int newlength);
//newarr = Arrays.copyOf(oldarr,newlength);
//表示將oldarr的全部內容複寫到newarr中,newarr的長度為newlength
System.arraycopy(oldarr, oldbegin, newarr, newbegin,length);
//將oldarr中的第oldbegin開始,長度為length的子數組複製到newarr的從newbegin開始的位置處。
比如oldarr={1,2,3}. newarr={5,6,7},oldbegin=1,newbegin=1,length=2.則執行後,結果為newarr為{5,2,3}.
比如oldarr={1,2,3,4}. newarr={5,6,7},oldbegin=1,newbegin=1,length=3.則執行後,結果為ArrayOutofBoundsException,因為newarr長度不夠
public ArrayList(int initialCapacity) { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);this.elementData = new Object[initialCapacity];}
//預設開始分配的大小10public ArrayList() {this(10);}
//如果當前capacity<minCapacity,則將數組的capacity增長到minCapacity
public void ensureCapacity(int minCapacity) {int oldCapacity = elementData.length;if (minCapacity > oldCapacity) {Object oldData[] = elementData;int newCapacity = (oldCapacity * 3) / 2 + 1;//newlength = (oldlength*3)/2+1if (newCapacity < minCapacity)newCapacity = minCapacity;elementData = Arrays.copyOf(elementData, newCapacity);//此語句是自增長數組的核心語句}}
添加元素
public boolean add(E e) {ensureCapacity(size + 1); //將size+1,如果capacity不夠,則重新分配elementData[size++] = e;return true;}
添加多個元素
public boolean addAll(Collection<? extends E> c) {Object[] a = c.toArray();int numNew = a.length;//新插入的元素大小ensureCapacity(size + numNew); //插入元素錢首先判斷容量夠不夠System.arraycopy(a, 0, elementData, size, numNew);//將a[0,...a,length-1] 放到 elementData[size,....size+numNew-1]中去size += numNew;return numNew != 0;}
移除元素
public E remove(int index) {RangeCheck(index);//看index是否在數組的界裡E oldValue = (E) elementData[index];int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index + 1, elementData, index,numMoved);elementData[--size] = null; //使得記憶體回收行程將其回收return oldValue;}