ArrayList是一基于動(dòng)態(tài)數(shù)組實(shí)現(xiàn)的
@Override
public boolean add(E object) {
Object[] a = array;
int s = size;
if (s == a.length) {
Object[] newArray = new Object[s +
(s < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : s >> 1)];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
}
a[s] = object;
size = s + 1;
modCount++;
return true;
}
如果一直使用的是add方法增加數(shù)據(jù)捕透,它的默認(rèn)長(zhǎng)度是12
private static final int MIN_CAPACITY_INCREMENT = 12;
當(dāng)沒(méi)次達(dá)到容量是丝格,就會(huì)擴(kuò)容撑瞧,大概是增長(zhǎng)50%,即
s+s>>1
所以容量的長(zhǎng)度變化是0显蝌,12预伺,18,27曼尊,40...以此類推(但具體值不一定是這樣酬诀,因?yàn)檫€存在addAll方法,兩者同時(shí)使用就不是這樣了)骆撇,擴(kuò)容后會(huì)講原先數(shù)據(jù)通過(guò)System.arraycopy復(fù)制一份給newArray料滥,那么newArray就是擴(kuò)容后并且有原先數(shù)據(jù)的新數(shù)組,隨后再對(duì)變量array賦值艾船,供下次使用
但如果其中使用addAll方法時(shí),原先數(shù)組的剩余容量小于新數(shù)據(jù)的長(zhǎng)度的話高每,則會(huì)進(jìn)行擴(kuò)容屿岂,這次它的基數(shù)是原先數(shù)組已有的數(shù)據(jù)長(zhǎng)度加上新數(shù)據(jù)的長(zhǎng)度
@Override public boolean addAll(Collection<? extends E> collection) {
Object[] newPart = collection.toArray();
int newPartSize = newPart.length;
if (newPartSize == 0) {
return false;
}
Object[] a = array;
int s = size;
int newSize = s + newPartSize; // If add overflows, arraycopy will fail
if (newSize > a.length) {
int newCapacity = newCapacity(newSize - 1); // ~33% growth room
Object[] newArray = new Object[newCapacity];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
}
System.arraycopy(newPart, 0, a, s, newPartSize);
size = newSize;
modCount++;
return true;
}
private static int newCapacity(int currentCapacity) {
int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : currentCapacity >> 1);
return currentCapacity + increment;
}
這邊源碼中雖然寫的注釋是33%左右的增加,但是我感覺還是50%左右鲸匿,因?yàn)橹皇菧p了1爷怀,再去執(zhí)行currentCapacity+currentCapacity >> 1,我也試過(guò)幾個(gè)數(shù)字带欢,這個(gè)increment值基本還是50%左右
remove方法使用的原理是將index之后的數(shù)據(jù)拷貝了一份运授,并放在原先數(shù)組中,而這些數(shù)據(jù)存放的起始位置就是原先的index乔煞,拷貝完成后將最后一位(這里的最后一位并不是指整個(gè)數(shù)組的最后一位吁朦,而是排在末尾的數(shù)據(jù),是有值的)置空
@Override
public E remove(int index) {
Object[] a = array;
int s = size;
if (index >= s) {
throwIndexOutOfBoundsException(index, s);
}
@SuppressWarnings("unchecked") E result = (E) a[index];
System.arraycopy(a, index + 1, a, index, --s - index);
a[s] = null; // Prevent memory leak
size = s;
modCount++;
return result;
}
remove方法并不會(huì)改變已有數(shù)據(jù)的長(zhǎng)度