Почему iterator.forEachRemaining не удаляет элемент в лямбде-приемнике?

Давайте посмотрим на этот пример:

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();
    }
}

И теперь, это работает отлично:

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

в то время как это вызывает исключение IllegalStateException:

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

У меня короткий вопрос: почему?

1 ответ

Решение

Обновлено благодаря @studro. Смотрите его комментарий ниже.

Документация API гласит:

Поведение итератора не определено, если базовая коллекция изменена во время выполнения итерации, кроме как путем вызова этого метода.

Кажется, что часть "неопределенное поведение" также применяется во время этой внутренней итерации.

Конечно, документация для forEachRemaining утверждает, что поведение эквивалентно

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

и если action::accept действительно звонил iterator.remove() приведенный фрагмент не должен выдавать никаких исключений (если remove является поддерживаемой операцией). Это может быть ошибка документации.

Другие вопросы по тегам