Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why iterator.forEachRemaining doesnt remove element in the Consumer lambda?

Lets have a look at this example:

public class ListIteratorTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("element1");
        list.add("element2");
        list.add("element3");
        list.add("element4");

        ListIterator<String> iterator = list.listIterator();
    }
}

And now, this works fine:

    // prints elements out, and then appropriately removes one after another
    while (iterator.hasNext()){
        System.out.println(iterator.next());
        iterator.remove();
    }

while this throws an IllegalStateException:

        // throws IllegalStateException, why?
        iterator.forEachRemaining(n -> {
            System.out.println(n);
            iterator.remove();
        });

My question is short: why?

like image 988
azalut Avatar asked Mar 23 '15 12:03

azalut


People also ask

What is the difference between forEach and forEachRemaining?

forEach iterates through the elements of an Iterable . forEachRemaining iterates through the remaining elements of an Iterator .

What is forEachRemaining?

The forEachRemaining() method of Java Interface Spliterator is used to performs the given action for each remaining element sequentially in the current thread until all elements have been processed or the action throws an exception.


1 Answers

Updated thanks to @studro. See his comment below.

The API documentation states:

The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.

It seems like the "unspecified behavior" part also applies during this internal iteration.

Granted, the documentation for forEachRemaining states that the behavior is equivalent to

while (hasNext())
    action.accept(next());

and if action::accept did in fact call iterator.remove() the above snippet should not throw any exception (if remove is a supported operation). This might be a documentation bug.

like image 63
aioobe Avatar answered Sep 26 '22 11:09

aioobe