public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable複製代碼
implemnts RandomAccess表明了其擁有隨機快速訪問的能力,能夠根據下標快速訪問元素java
ArrayList底層是數組,會佔據連續的內存空間(數組的長度>真正數據的長度), 數組的缺點:空間效率不高。
當添加元素,超出現有數組容量時,便會進行擴容操做:
ArrayList的增加因子1,擴容1/2複製代碼
public void ensureCapacity(int minCapacity) {//設定初始容量的構造函數
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
?0
// larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); }} //如下三個方法實現了Array擴容的操做 private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++;//擴容一定致使此值++ // overflow-conscious code if (minCapacity - elementData.length > 0)//目標長度>現有長途條件下 grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1);//擴容容量爲舊容量的1.5倍,增加因子爲1/2 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);//此方法最總會調用System.ArrayCopy() } public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); } //System類中的靜態方法,這是一個native方法. //經過此方法實現複製出新數組,實現數組的擴容(其是對對象引用的複製-淺度複製) public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)複製代碼
int modCount: 每次數組結構改變都會modCount++(增長致使擴容,或者刪)數組
private int size; 集合數據的長度-list.size()獲取的值bash
transient Object[] elementData;真正的存儲東西的元素數組. 長度會>= sizedom
修飾詞:transient,不參與序列化。 通常數組的容量會大於所存元素的個數,因此不必所有參與序列化,浪費多餘空間.在writeObject()中序列化真正存儲數據的元素就能夠了.複製代碼
數組的結構改變標識爲modCount的值改變了ide
System.arraycopy()
是一個native的數組之間複製的操做,由集合中的grow(minCapacity) 方法控制函數
👇是ArrayList的增刪改查方法裏,☝兩個關鍵數據的變化的狀況ui
##1.增---public boolean add(E e)
`modCount++
if (minCapacity - elementData.length > 0)`----若是新集合長度>如今數組長度 會`grow(minCapacity)`;複製代碼
##2.刪---remove(Object o)this
`modCount++
grow(minCapacity);`複製代碼
##3. 改---set(int index, E element)spa
兩個操做都沒發生複製代碼
##4.查---contains(Object o) ,indexOf(Object o)code
兩個操做都沒發生複製代碼
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;//將modCount的值記錄下來
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();//每次都會先檢查是否發生過結構改變(modCount值是否相同)
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();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}}複製代碼
增,刪,改,查等每次都會先檢查是否索引越界
增刪數組確定會修改modCount的值
System.arrayCopy()發生條件:a集合增長致使擴容,b刪除元素。而集合的改查不會發生數組拷貝
結合安卓加載數據使用場景, 列表展現經常使用,查是高頻操做,增刪較少,因此ArrayList最合適 複製代碼
zyt