删除List中的元素

有时候会有这种场景,在遍历list的过程中,需要删除掉一部分元素。如果不注意的话,很容易就写出下面的代码:

public class ListRemoveTest {
    public static void main(String[] args) {
        List<String> removeList = new ArrayList<String>();
        removeList.add("a");
        removeList.add("b");
        removeList.add("c");
        removeList.add("d");
        for (int i = 0; i < removeList.size(); i++) {
            removeList.remove(i);
        }
        System.out.println(removeList.size());
    }
}

程序的运算结果输出为2,本以为会输出0,但是为什么是2呢?下面看下ArrayList的remove方法源码:

/**
 * Removes the element at the specified position in this list.
 * Shifts any subsequent elements to the left (subtracts one from their
 * indices).
 *
 * @param index the index of the element to be removed
 * @return the element that was removed from the list
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
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; // clear to let GC do its work
    return oldValue;
}

/**
 * Checks if the given index is in range.  If not, throws an appropriate
 * runtime exception.  This method does *not* check if the index is
 * negative: It is always used immediately prior to an array access,
 * which throws an ArrayIndexOutOfBoundsException if index is negative.
 */
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

当传入要删除的位置index之后,rangeCheck方法会先进行判断,如果index大于等于数组的长度,则直接抛出IndexOutOfBoundsException异常。然后modCount加1(涉及到快速失败机制,此处略过)。
之后会利用 System.arraycopy方法,把index位置后面的元素向前拷贝一个位置。再把最后一个位置置为null,方便进行垃圾回收。所以,当调用list.remove()方法时,这个list就变了。
上面代码中,当i=0的时候,第一次调用remove方法,把第一个元素删除掉之后,list的size就变成3了,并且原来第二个位置的元素被拷贝到了第一个位置。接下来i=1,实际删除掉是原来第三个元素。等原来的第三个元素删除后,list的size变成了2,然后i=2,再remove(2)的时候,此时这个位置已经没有元素了。所以最后还会剩下b和d两个元素。
所以,直接用这种方式删除是不可以的,如果要删除list中的元素的话,需要通过迭代器。

List<String> iteratorList = new ArrayList<String>();
iteratorList.add("1");
iteratorList.add("2");
iteratorList.add("3");
Iterator iterator = iteratorList.iterator();
while (iterator.hasNext()) {
    iterator.next();
    iterator.remove();
}
System.out.println(iteratorList.size());

程序输出结果:0

猜你喜欢

转载自blog.csdn.net/chayangdz/article/details/77116156