An Iterable supplies an Iterator for traversal. The common enhanced-for path is only one valid usage: it checks hasNext(), calls next(), runs the body, and repeats. section 8.13
The central mistake is implementing an iterator that works only when hasNext() precedes every next(). Collection utilities may call next() first, repeat operations, or expose exhaustion directly. section 8.13
Correct range iterator
A range iterator keeps state in next(), checks exhaustion, and throws NoSuchElementException when no element remains. IntStream.range(0, max).iterator() avoids custom implementation when suitable.
Apply these safeguards when exposing an Iterable:
- Make next() work without a preceding hasNext() and throw NoSuchElementException after exhaustion. section 8.13






