1. 程式人生 > >Java原始碼分析--java.util.ArrayList

Java原始碼分析--java.util.ArrayList

  • 序列化問題
/** 使用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;
}