Skip to main content
added 10 characters in body
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

One of the performance issues of iterators is that each time you call next()next(), you call hasNext()hasNext() twice... consider a typical iterator use case:

  • reduces the multiple hasNext()hasNext() calls to a simple boolean check
  • the advance method is called only once per item
  • it handles null values in both the iteratorOfIteratorsiteratorOfIterators and in the currentIteratorcurrentIterator

One of the performance issues of iterators is that each time you call next(), you call hasNext() twice... consider a typical iterator use case:

  • reduces the multiple hasNext() calls to a simple boolean check
  • the advance method is called only once per item
  • it handles null values in both the iteratorOfIterators and in the currentIterator

One of the performance issues of iterators is that each time you call next(), you call hasNext() twice... consider a typical iterator use case:

  • reduces the multiple hasNext() calls to a simple boolean check
  • the advance method is called only once per item
  • it handles null values in both the iteratorOfIterators and in the currentIterator
Source Link
rolfl
  • 98.2k
  • 17
  • 220
  • 419

Reversing the logic a little bit on iterators can often make a big difference in the way the code reads, and it can remove code duplication.

One of the performance issues of iterators is that each time you call next(), you call hasNext() twice... consider a typical iterator use case:

while (it.hasNext()) {
    Object o = it.next();
    ... do something with o.
}

Now, you call hasNext() in the loop, and, internally, the first thing next() does, is call hasNext() again.

If the hasNext() method is 'heavy', it can be quite expensive. This is especially true because, often, most of the same work is required yet again, to perform the next() (a third time!).

There is a trick to prevent this work duplication: Do the work once in advance, and remember the state.

public class IteratorOfIterator implements Iterator<Integer>{

    private final Iterator<Iterator<Integer>> iteratorOfIterator;
    private Iterator<Integer> currentIterator = null;
    private Integer next = null;
    private boolean isvalid = false;

    public IteratorOfIterator(Iterator<Iterator<Integer>> iterator)  {
        this.iteratorOfIterator = iterator;
        // call advance from the constructor!!
        advance();
    }

    private void advance() {
        if (currentIterator != null && currentIterator.hasNext()) {
            isvalid = true;
            next = currentIterator.next();
            return;
        }
        currentIterator = null;
        while (currentIterator == null && iteratorOfIterator.hasNext()) {
            currentIterator = iteratorOfIterator.next();
            if (currentIterator != null && currentIterator.hasNext()) {
                next = currentIterator.next();
                isvalid = true;
                return;
            }
        }
        next = null;
        isvalid = false;
    }

    @Override
    public boolean hasNext() {
        return isvalid;
    }

    @Override
    public Integer next() {
        if (isvalid) {
            throw new NoSuchElementException("the stuff cannot be null.");
        }
        Integer val = next;
        advance();
        return val;
    }


    @Override
    public void remove() {
        throw new UnsupportedOperationException("The remove operation is not supported.");
    }
}

The above code:

  • reduces the multiple hasNext() calls to a simple boolean check
  • the advance method is called only once per item
  • it handles null values in both the iteratorOfIterators and in the currentIterator