NoSuchElementException signals that an iterator or enumeration has no next element. Iterator implementations must throw it when next() is called after the elements are exhausted. section 8.13
A broken iterator can pass a for-each loop
An iterator whose hasNext() advances state may appear correct in for (int value : range(10)), because enhanced for calls hasNext() before each next(). Collections.min(range(10)) instead begins with next(), exposing the contract violation and potentially causing incorrect behavior or NoSuchElementException. section 8.13
Avoid the failure by following these iterator rules:
- Keep hasNext() from consuming or advancing the next element. section 8.13
- Make next() check exhaustion and throw NoSuchElementException when no element remains. section 8.13
- Buffer values when hasNext() reads ahead, then clear the buffer after next() returns the value. section 8.13
public Iterator<Integer> iterator() {
return new Iterator<>() {
int cur = 0;
public boolean hasNext() {
return cur < max;
}
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return cur++;
}
};
}
Use this corrected numeric iterator as a compact reference for exhaustion checks and state advancement. section 8.13
