Why does iterator.remove not throw a ConcurrentModificationException

What iterator.remove()is the difference from list.remove(), so that the iterator does not throw an exception, but list.remove()throws it? In the end, both resize the collection.

Please ignore multithreading here. I'm just talking about a for-each loop and an iterator loop. As far as I know, the for-each loop creates an iterator only internally.

I'm confused.

+15
source share
5 answers

ConcurrentModificationExceptionis not generated Iterator.remove()because it is a legal way to modify the collection during iteration. Here is what javadoc says for Iterator:

, ( ). next(). , , .

, , , ( ), . ( ConcurrentModificationException: javadocs, , )

, , .


iterator.remove list.remove , , list.remove ?

№ 1. , 1. , . (, .)

№ 2. -. , , . , . .


for-each . , .

. for-each - while .

, :

    for (int i = 0; i < list.size(); i++) {
        if (...) {
            list.remove(i);
        }
    }

ConcurrentModificationException, , , 2.


1 - To achieve "exactly once" iteration behavior, when you remove an element via the collection object, the iterator data structure would need to be updated to keep it in step with what has happened to the collection. This is not possible in the current implementations because they don't keep links to the outstanding iterators. And if they did, they would need to use [TG47] objects or risk memory leaks.

2 - Or even get an [TG48]. And if the collection is not concurrent / properly synchronized, you can get worse problems.

+12

, , , list.remove() list.remove() ConcurrentModificationException, iterator.remove() - ?

:

    List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c", "d"));

    for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
        if (iter.next().equals("b")) {
            // iter.remove();    // #1
            // list.remove("b"); // #2
        }
    }

# 1, . # 2 ( # 1), iter.next() iter.next() ConcurrentModificationException.

, - , . , , , , , , .. ConcurrentModificationException .

, , , .

iterator.remove() , . , , , , . :

    Iterator<String> i1 = list.iterator();
    Iterator<String> i2 = list.iterator();
    i1.remove();
    i2.remove();

, . , , i2.remove() i2.remove() ConcurrentModificationException.

+27

. List.remove(), , - . Iterator.remove(), , .

+3

, , . ArrayLists:

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

    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size) throw new NoSuchElementException();
        // ...
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        // ...
        ArrayList.this.remove(lastRet);
        // ...
        cursor = lastRet;
        lastRet = -1;
    }

:

List list = new ArrayList(Arrays.asList(1, 2, 3, 4));
Iterator it = list.iterator();
Integer item = it.next();

list.remove(0);

it.remove() , 2, , lastRet.

if (item == 1) {
   it.remove(); // list contains 3, 4
}

! , remove() , next(), . .

. HashMap, . , , , .

, iterator.remove() , , . remove() , , .

0
public class ArrayListExceptionTest {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("a");
        list1.add("b");
        list1.add("c");
        Iterator<String> it1 = list1.iterator();
        ArrayList<String> list2 = new ArrayList<String>();
        list2.add("a");
        try {

            while (it1.hasNext()) {
                list1.add(it1.next());
            }
        } catch (ConcurrentModificationException e) {
            e.printStackTrace();
        }
        it1 = list1.iterator();
        while (it1.hasNext()) {
            System.out.println(it1.next());
        }
        it1 = list1.iterator();
        try {
            while (it1.hasNext()) {
                if (it1.next().equals("a"))
                    list1.retainAll(list2);
            }

        } catch (ConcurrentModificationException e) {
            e.printStackTrace();
        }
        it1 = list1.iterator();
        while (it1.hasNext()) {
            System.out.println(it1.next());
        }
        it1 = list1.iterator();
        Iterator<String> it2 = list1.iterator();
        it1.remove();
        it2.remove();
    }
}

3

1: , , , next() ConcurrentModificationException.

2: , retain(), , next(), ConcurrentModificationException.

3: java.lang.IllegalStateException, ConcurrentModificationException.

:

a
b
c
a

a
a

    java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
        at java.util.ArrayList$Itr.next(ArrayList.java:859)
        at com.rms.iteratortest.ArrayListExceptionTest.main(ArrayListExceptionTest.java:21)
    java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
        at java.util.ArrayList$Itr.next(ArrayList.java:859)
        at com.rms.iteratortest.ArrayListExceptionTest.main(ArrayListExceptionTest.java:37)
    Exception in thread "main" java.lang.IllegalStateException
        at java.util.ArrayList$Itr.remove(ArrayList.java:872)
        at com.rms.iteratortest.ArrayListExceptionTest.main(ArrayListExceptionTest.java:55)
0
source

All Articles