ArrayList只寫add方法了赂蠢,其他的方法感興趣的自己看一下幔戏,都比較簡單拼卵。
構(gòu)造函數(shù)
public ArrayList(int initialCapacity) {
// 如果初始容量大于0,則創(chuàng)建一個initialCapacity大小的數(shù)組
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 初始容量等于0惠啄,則用初始數(shù)組
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
// 無參構(gòu)造函數(shù),用默認數(shù)組合敦,并且默認的的容量是10
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public ArrayList(Collection<? extends E> c) {
// elementData被賦值為元素數(shù)組
elementData = c.toArray();
// 元素個數(shù)(size)被賦值為elementData的長度
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
// 數(shù)組拷貝
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
添加元素
需要的常量
// 默認數(shù)組
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 默認容量
private static final int DEFAULT_CAPACITY = 10;
// 數(shù)組的最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
public boolean add(E e) {
// 調(diào)整容量
ensureCapacityInternal(size + 1); // Increments modCount!!
// 調(diào)整完容量加入元素
elementData[size++] = e;
return true;
}
// 調(diào)整容量
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// 計算添加元素所需要的最小容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 如果是第一次add牲迫,則返回默認容量和當(dāng)前minCapacity的最大值
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
// 若不是第一次add,則返回minCapacity
return minCapacity;
}
// 調(diào)整容量
private void ensureExplicitCapacity(int minCapacity) {
// 修改次數(shù)自增
modCount++;
// 若添加元素所需的容量比當(dāng)前數(shù)組長度小了衡楞,則擴容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// 真正擴容
private void grow(int minCapacity) {
// 原容量
int oldCapacity = elementData.length;
// 新容量是原容量的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 新容量還是不夠吱雏,那么新容量就等于minCapacity
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 新容量溢出了
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 拷貝一個新數(shù)組
elementData = Arrays.copyOf(elementData, newCapacity);
}
// 容量溢出處理
private static int hugeCapacity(int minCapacity) {
// 已經(jīng)超出int范圍了,拋OutOfMemoryError
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
// 沒超出返回新容量
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
minCapacity代表添加元素所需要的容量,等于原容量+添加的元素個數(shù)
Q&A
Q:最大數(shù)組容量MAX_ARRAY_SIZE為啥是 Integer.MAX_VALUE - 8歧杏?
A:數(shù)組作為一個對象镰惦,需要一定的內(nèi)存存儲對象頭信息,對象頭信息最大占用內(nèi)存不可超過8字節(jié)犬绒。
最后一點需要注意的
java.util包下的集合為啥都不支持增強for或者迭代器迭代修改集合旺入?
答案在ArrayList的迭代器代碼中找。
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;
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
// 注意
checkForComodification();
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();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
????可以看到每次調(diào)用迭代器的next方法獲取下一個元素的時候凯力,總是會執(zhí)行checkForComodification茵瘾,這個方法會對比modCount和expectedModCount是否一致,如果不一致則拋出ConcurrentModificationException咐鹤。而add拗秘、remove、clear等方法都會修改modCount的值祈惶。
????調(diào)用迭代的remove方法則不會有這個問題聘殖,因為每次remove都會更新expectedModCount的值