// 序列化ID
private static final long serialVersionUID = 8683452581122892189L;
// 默認初始化容量
private static final int DEFAULT_CAPACITY = 10;
// 空數組
private static final Object[] EMPTY_ELEMENTDATA = {};
// 空數組
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 存儲數據元素的數組
transient Object[] elementData; // non-private to simplify nested class access
// 當前arraylist集合的大小,也就是elementData數組中數據元素的個數
private int size;
複製代碼
/**
* 一:無參構造方法
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 二:攜帶一個int類型的參數,指定arraylist的初始容量
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
複製代碼
能夠看到,在構造方法中直接將 elementData 指向 DEFAULTCAPACITY_EMPTY_ELEMENTDATA空數組,這個時候該ArrayList的size爲初始值0。java
進行參數校驗:
參數大於0,則指定數組長度;
參數等於0,則爲空數組;
參數小於0,則拋異常。數組
/**
* 一:直接添加數據元素到arraylist的尾部
*/
public boolean add(E e) {
//是否擴容、記錄modCount
ensureCapacityInternal(size + 1); // Increments modCount!!
//把值添加到數組尾部
elementData[size++] = e;
return true;
}
----------------------------------------------------------------------
private void ensureCapacityInternal(int minCapacity) {
//minCapacity=size+1;
//minCapacity表示若是添加成功後,數組的最小長度
//若是爲無參構造
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//取默認長度和minCapacity的最大值,即10
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//是否擴容
ensureExplicitCapacity(minCapacity);
}
----------------------------------------------------------------------
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 若是添加後最小長度大於 數組長度
if (minCapacity - elementData.length > 0)
//擴容
grow(minCapacity);
}
----------------------------------------------------------------------
private void grow(int minCapacity) {
//獲取數組長度
int oldCapacity = elementData.length;
//1.5倍擴容
int newCapacity = oldCapacity + (oldCapacity >> 1);
//1.5倍擴容也不夠用
if (newCapacity - minCapacity < 0)
//擴容後長度=minCapacity
newCapacity = minCapacity;
//簡直最大長度
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 複製
elementData = Arrays.copyOf(elementData, newCapacity);
}
複製代碼
代碼中已經有註釋了,很清晰。bash
/*
* 一:根據角標進行remove操做
*/
public E remove(int index) {
// 1. 對角標越界進行判斷
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
// 2.modCount自增1
modCount++;
// 3.獲取到指定下角標位置的數據
E oldValue = (E) elementData[index];
// 4.計算須要移動的元素個數
int numMoved = size - index - 1;
if (numMoved > 0)
// 5. 指定角標位置後的元素前移一位,效率低
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 6.將size自減1,並將數組末尾置爲null,便於垃圾回收
elementData[--size] = null; // clear to let GC do its work
// 7.最後將所要刪除的數據元素return掉
return oldValue;
}
/*
* 二:根據數據元素進行remove操做
*/
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 void fastRemove(int index) {
// 1.modCount的值自增1
modCount++;
// 2.計算須要移動的元素個數
int numMoved = size - index - 1;
if (numMoved > 0)
// 3. 指定角標位置後的元素前移一位
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 4.將size自減1,並將數組末尾置爲null,便於垃圾回收
elementData[--size] = null; // clear to let GC do its work
}
複製代碼
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
//檢查modCount
checkForComodification();
try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
----------------------------------------------------------------------
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
----------------------------------------------------------------------
final void checkForComodification() {
if (expectedModCount != ArrayList.this.modCount)
throw new ConcurrentModificationException();
}
複製代碼
public E get(int index) {
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index);
}
----------------------------------------------------------------------
E elementData(int index) {
return (E) elementData[index];
}
複製代碼
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
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;
}
複製代碼
未命名文件.jpg併發
ail-fast機制是集合中的一種錯誤檢測機制,咱們在操做集合中常常會遇到 java.util.ConcurrentModificationException異常,產生該異常的緣由就是fail-fast機制。函數
實現:若是在迭代期間計數器被修改,那麼hasNext或next將拋出concurrentModificationException
缺點:這種檢查是沒有同步的狀況下進行的,所以可能會看到失效的計數值,而迭代器可能並無意識到已經發生了修改。這是一種設計上的權衡,從而下降了併發修改操做的檢測代碼對程序性能帶來的影響。性能