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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43210354/article/details/82716932
今日推荐