嘟哝之JDK -- ArrayList

简介

ArrayList是一个可变数组,内部封装一个Object[]数组用于存放元素。

删除

删除动作都是通过public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);接口完成的。其中removeAllretainAll的算法是先将要保留的元素放到数组的头部,然后在通过arrayCopy完成。具体代码如下:

private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData;
    int r = 0, w = 0;
    boolean modified = false;
    try {
        for( ; r < size; r++)
            if((c.contains(elementData[r]) == complement)
                elementData[w++] = elementData[r];
    } finally {
        if(r != size) {
            System.arrayCopy(elementData, r, elementData, w, size - r);
        w += size - r;

        if(w != size) {
            for(int i = w; i < size; i++)
                    elementData[i] = null;
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}

其中,complementtrue的时候用于retainAll,为falseremoveALl。执行removeAll时,contains抛出异常, 返回值为false。

增加元素时动态扩容

首先看ArrayList的域变量:

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size; 

其中,创建ArrayList且未指定容量大小时,用DEFAULTCAPACITY_EMPTY_ELEMENTDATA初始化elementData。当创建ArrayList且指定容量为0时,用EMPTY_ELEMENTDATA初始化elementData

除了ArrayList(Collection<? extends E> c)之外,通过两外两种方式创建的对象,都只会在第一次add的时候分配内存空间。

扩容代码

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0 )
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

其中,用到了Arrays类的copyOf方法创建新的数组并将原有元素拷贝,如果新数组容量大于原有数组容量,新增加的位置将会初始化为0或null。

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    T[] copy = ((Object) newType == (Object)Object.class) ? (T[] new Object[newLength] : (T[] Arrays.newInstance(newType.getComponentType, newLength);
    System.arrayCopy(original, 0, copy, 0, Math.min(original.length, newLength));
    return copy;
}

另外,还可以通过ensureCapacity(int minCapacity)主动扩容。

缩容

ArrayListsize用于表示当前数组中元素的个数,当size小于数组长度length时,可以通过trimToSize缩减存储占用。

public void trimToSize() {
    modCount++;
    if(size < elementData.length) {
        elementData = (size == 0) ? EMPTY_ELEMNTDATA : Arrays.copyOf(elementData, size);
    }
}

迭代器

ArrayList成员变量int modCount用于保存所有对ArrayList修改的次数。这个值被IteratorListIterator用来判断使用迭代器的过程中是否存在同步更改ArrayList的情况。

ArrayList支持两种迭代器,一种实现了接口Iterator,另一种实现了ListIterator。前者用于遍历和删除,后者用于插入、双向遍历和删除。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值