Iterator.forEachRemaining and Iterator.remove

Martin Buchholz martinrb at
Tue Oct 25 22:16:25 UTC 2016

Actually, the ArrayList implementation updates fields only at the end of
the iteration, so if an action throws in the middle, the iterator is
semi-corrupted (in the sense that remove() will remove the "wrong" element
and next will return previously visited elements).  I think it's best to
say in the spec that after calling forEachRemaining, subsequent operations
on the Iterator are undefined (whether or not the action throws).  For
consistency, we should probably keep the historic behavior that remove()
after forEachRemaining() removes the last element, even though that is not
to be encouraged.

On Tue, Oct 25, 2016 at 2:30 PM, Paul Sandoz <paul.sandoz at> wrote:

> Hi Martin,
> Hmm…
> The intent of ArrayList/Vector/LinkedList implementations is clear, leave
> the iterator in the same state as a last successful next call.
> I believe ArrayDeque’s iterator (in repo, unsure about your updates) has
> different behaviour e.g.
>   ad.forEachRemaining(…);
>   ad.remove(); // which element is removed?
> We also don’t say anything about the behaviour if remove is called by the
> consumer function. This is potentially more problematic since we often
> optimize for the bulk operation and don’t update state within the loop.
> I am inclined to say the behaviour in both cases is undefined, which we
> could mention in the documentation.
> Paul.
> > On 24 Oct 2016, at 12:32, Martin Buchholz <martinrb at> wrote:
> >
> > It doesn't make a lot of sense for users to call Iterator.remove after
> calling Iterator.forEachRemaining.
> >
> > The default implementation has no choice but to do
> >
> >         while (hasNext())
> >             action.accept(next());
> >
> > upon which remove() removes the last element.  What should overriding
> implementations do?  Emulate the default implementation's behavior or throw
> IllegalStateException, or even remove the element returned by the last
> actual call to next?  The spec is (perhaps intentionally) unclear on this
> point.  I'm thinking we emulate the default implementation's behavior,
> because common collections like ArrayList work this way, and some users may
> be depending on it, perhaps unwisely.

More information about the core-libs-dev mailing list