List三种遍历时对集合进行删除操作的验证

2019-08-06  本文已影响0人  SmileMylife

1.使用for循环遍历集合,并进行删除。

情况一:

ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
for (int i = 0; i < arrayList.size(); i++) {
    if (arrayList.get(i) == 3) {
        arrayList.remove(i);
    }
}
结果:[1, 2]

情况二:

ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
for (int i = 0; i < arrayList.size(); i++) {
    if (arrayList.get(i) == 1) {
        arrayList.remove(i);
    }
}
结果:[2, 3]

情况三:

ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
for (int i = 0; i < arrayList.size(); i++) {
    if (arrayList.get(i) == 2) {
        arrayList.remove(i);
    }
}
结果:[1, 3]

2.使用foreach迭代

情况一:

ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
for (Object i : arrayList) {
    if (Integer.parseInt(i.toString()) == 1) {
        arrayList.remove(i);
    }
}
结果:Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at test.test.IteratorTest.main(IteratorTest.java:21)

情况二:

ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
for (Object i : arrayList) {
    if (Integer.parseInt(i.toString()) == 2) {
        arrayList.remove(i);
    }
}
结果:[1, 3]

情况三:

ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
for (Object i : arrayList) {
    if (Integer.parseInt(i.toString()) == 3) {
        arrayList.remove(i);
    }
}
结果:Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at test.test.IteratorTest.main(IteratorTest.java:15)

3.使用迭代器进行迭代。

ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
Iterator<Integer> iterator = arrayList.iterator();
while (iterator.hasNext()) {
    Integer next = iterator.next();
    if (next == 3) {
        iterator.remove();
    }
}
System.out.println(arrayList.toString());
结果:[1,2]

使用迭代器是正确的选择,但是为什么foreach会报错呢?

源码如下:

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

这是arraylist的一个内部类,而foreach本质上也是使用迭代器进行遍历,但是在每次迭代的时候会去校验集合中元素的个数是否有变更,如果有变更则抛出并发修改异常。

上一篇 下一篇

猜你喜欢

热点阅读