ArrayList源码(2)

现在接着说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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值