ArrayList源码(2)

来源:互联网 发布:软件部署实施方案 编辑:程序博客网 时间:2024/06/01 09:45

现在接着说ArrayList的另外一个常用方法remove().
remove同样也是存在两个方法
1.

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);    elementData[--size] = null; // Let gc do its work    return oldValue;}

第一步和add里面rangeCheckForAdd(index);相似但是并不完全相同

private void rangeCheck(int index) {    if (index >= size)        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}

并没有判断index<0的情况,这个为什么呢?我没有想明白运行肯定出现错误

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1    at java.util.ArrayList.elementData(ArrayList.java:371)    at java.util.ArrayList.remove(ArrayList.java:448)    at Test.DateTest.main(DateTest.java:21)

难道是因为肯定会报错就不用判断了??恕我才能浅薄,大家如果有知道的请告诉我一声。
之后把将要移除的数据拿出并返回,数组的长度进行改变之后执行数组复制的操作,我找了个该方法说明的博客: System.arraycopy方法的使用。最后将数组的最后一位设置为null。
2.

public boolean remove(Object o) {    if (o == null) {        for (int index = 0; index < size; index++)            if (elementData[index] == null) {                fastRemove(index);                return true;            }    } else {        for (int index = 0; index < size; index++)            if (o.equals(elementData[index])) {                fastRemove(index);                return true;            }    }    return false;}

这个分两种情况传来的值是否为null,如果为null,则进行对比,是否List数组中是否有null,然后将其删除,如果不是同样是遍历List来对比。
将数据从List数组中移除的方法又是:

private void fastRemove(int index) {    modCount++;    int numMoved = size - index - 1;    if (numMoved > 0)        System.arraycopy(elementData, index+1, elementData, index,                         numMoved);    elementData[--size] = null; // Let gc do its work}

这段代码在remove(index)里面都有,那为什么不写成这样呢?

public E remove(int index) {    rangeCheck(index);    E oldValue = elementData(index);    fastRemove(index);    return oldValue;}

大家想想为什么??说出来
接下来是remove的另外两个方法:

public boolean removeAll(Collection<?> c) {    return batchRemove(c, false);}public boolean retainAll(Collection<?> c) {    return batchRemove(c, true);}    

全用到了batchRemove只是传的第二个参数不同。

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 {        // Preserve behavioral compatibility with AbstractCollection,        // even if c.contains() throws.        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;}

大家应该知道removeAll是将相同的都删除, 留下不相同的。retainAll是将不相同的都删除,留下相同的。
代码简单,注意他们最后再遍历一遍将空出的个数最后几个都设置为null。这个在之后大家写相关的代码时一定要注意。
remove的内容都说完了,还有一个相似的clear(),这个没有啥内容。

public void clear() {    modCount++;    // Let gc do its work    for (int i = 0; i < size; i++)        elementData[i] = null;    size = 0;}
原创粉丝点击