-
Bug
-
Resolution: Fixed
-
P4
-
None
There's a fairly clear contract about the behavior of Iterator.remove() when traversing via next(), but there's less clarity when traversing via forEachRemaining.
The default implementation has no choice but to do
while (hasNext())
action.accept(next());
For which remove() can be called even within an action, and afterwards remove() removes the last element successfully returned by next(), even if one of the actions threw. Typical implementations do not provide this, naturally optimizing the updates of the Iterator fields until all the actions have been called. The situation is a bit messy, and it's probably too late to provide such guarantees in the spec now. I suggest:
- Spec is updated to make it clear that modifying the underlying collection while forEachRemaining is in progress, even via Iterator.remove(), is not defined behavior. Calling remove() after forEachRemaining is also not defined.
- In actual collection implementations, we ensure fairly sensible behavior consistent with the default implementation. If an action throws, then remove() should remove either the last element passed to the action or the iteration should be exhausted. Current implementations get "corrupted" in case of an action throwing, in the sense that elements previously passed to the action may be returned again by next(). This should be fixed even though it's QOI.
http://markmail.org/search/?q=Iterator.forEachRemaining%20and%20Iterator.remove#query:Iterator.forEachRemaining%20and%20Iterator.remove%20list%3Anet.java.openjdk.core-libs-dev+page:1+state:facets
The default implementation has no choice but to do
while (hasNext())
action.accept(next());
For which remove() can be called even within an action, and afterwards remove() removes the last element successfully returned by next(), even if one of the actions threw. Typical implementations do not provide this, naturally optimizing the updates of the Iterator fields until all the actions have been called. The situation is a bit messy, and it's probably too late to provide such guarantees in the spec now. I suggest:
- Spec is updated to make it clear that modifying the underlying collection while forEachRemaining is in progress, even via Iterator.remove(), is not defined behavior. Calling remove() after forEachRemaining is also not defined.
- In actual collection implementations, we ensure fairly sensible behavior consistent with the default implementation. If an action throws, then remove() should remove either the last element passed to the action or the iteration should be exhausted. Current implementations get "corrupted" in case of an action throwing, in the sense that elements previously passed to the action may be returned again by next(). This should be fixed even though it's QOI.
http://markmail.org/search/?q=Iterator.forEachRemaining%20and%20Iterator.remove#query:Iterator.forEachRemaining%20and%20Iterator.remove%20list%3Anet.java.openjdk.core-libs-dev+page:1+state:facets
- relates to
-
JDK-8166446 SingletonIterator.forEachRemaining doesn't advance before calling action
-
- Closed
-