web-dev-qa-db-ja.com

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

私の質問は短いです:なぜですか?

11
azalut

@studroのおかげで更新されました。以下の彼のコメントを参照してください。

APIドキュメント の状態:

このメソッドを呼び出す以外の方法で反復の進行中に基になるコレクションが変更された場合、イテレーターの動作は指定されません。

「不特定の動作」の部分は、この内部反復中にも適用されるようです。

確かに、forEachRemainingのドキュメントには、動作は同等であると記載されています

_while (hasNext())
    action.accept(next());
_

_action::accept_が実際にiterator.remove()を呼び出した場合、上記のスニペットは例外をスローしないはずです(removeがサポートされている操作の場合)。これはドキュメントのバグである可能性があります。

17
aioobe