Java原始碼分析--java.util.ArrayList
阿新 • • 發佈:2018-12-10
- 序列化問題
/** 使用transient關鍵字,即使繼承了Serializable,也不會序列化
* 一般情況下 elementData.capacity < element.size,我們並不希望將空的元素也序列化
* ps: 可以看到ArrayList操作的陣列
* */
private transient Object[] elementData;
// ArrayList提供了兩個方法,序列化和反序列化時只操作有效元素
private void writeObject(java.io.ObjectOutputStream s);
private void readObject (java.io.ObjectInputStream s);
- ArrayList擴容機制
//這裡的minCapacity=size+k,當add k個新元素時,capacity最少要size+k
private void ensureCapacityInternal(int minCapacity) {
if (elementData == 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被擴容
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;//如果1.5被仍然不能滿足,則要多少給多少
if (newCapacity - MAX_ARRAY_SIZE > 0)// 1.5被的oldCapaticy太大 或 需求minCapacity太大
newCapacity = hugeCapacity(minCapacity);
// 這裡涉及到新陣列的create and copy,所以儘量避免擴容
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
- toArray:elementData 屬於 ArrayList 內部 private 屬性,這裡是copy一份陣列返回,而不是返回 elementData 的引用,維護了封裝的特性。
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
- 插入元素以及刪除元素:都要對index後面的所有元素進行移位
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);//index後面的所有元素都要後移一位
elementData[index] = element;
size++;
}
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);//index後面的元素都要前移一位
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}