Calling Iterator.hasNext()
is not supposed to have any side effects and hence should not change the iterator’s state.
Iterator.next()
advances the iterator by one item. So calling it inside Iterator.hasNext()
breaks the hasNext()
contract and will lead to unexpected behavior in production.
How to fix this issue strongly depends on the specific implementation of the iterator. Make sure that the logic of the hasNext()
implementation does not change the state of the iterator or any underlying data sources. Instead, it should merely return state information.
class MyIterator implements Iterator<Integer> { private Queue<Integer> elements; ... @Override public boolean hasNext() { try { next(); // Noncompliant, next() is called from hasNext() return true; } catch (NoSuchElementException e) { return false; } } @Override public Integer next() { return elements.remove(); } }
class MyIterator implements Iterator<Integer> { private Queue<Integer> elements; ... @Override public boolean hasNext() { return !elements.isEmpty(); // Compliant, no call to next() } @Override public Integer next() { return elements.remove(); } }