I have an implementation of java.util.Iterator which requires that the call to next() should always be proceeded by a call to hasNext(). (This is because results are returned asynchronosly in a multi threaded environment and it is never clear how many more results there might be).
Would it be 'correct' to properly document this in the JavaDoc and then throw a RuntimeException if this was violated. Or is this stretching the Iterator interface a little too far?
All thoughts appreciated?
I might be missing something here, but why not call hasNext() internally in your implementation?
Requiring that hasNext() be called before next() violates the iterator contract. You really should rewrite it so that next() simply throws a NoSuchElementException if there is no element to return.
I imagine you're doing something like this:
class IteratorImpl<T> implements Iterator<T> {
private Source<T> source = ...
private T next = null;
public boolean hasNext() {
if(next == null) {
next = source.poll();
}
return next != null;
}
That sounds OK to me. I can't imagine a situation where you'd want to use next without hasNext - it would be a recipe for exceptions.
EDIT:
The doc for hasNext() says:
Returns true if the iteration has more elements. (In other words, returns true if next would return an element rather than throwing an exception.)
To me, the implementation does not violate the contract. However, I would (as Fabian Steeg implies) still implement next() as:
public T next() {
if(!hasNext()) {
throw new NoSuchElementException();
}
T ret = next;
next = null;
return ret;
}
I mean, what does that check really cost you?
You must check and throw a NoSuchElementException as per the API contract. Either testing on !hasNext() or next == null will meet this criteria, I believe, but I would favour the former.
If someone is catching NoSuchElementException instead of calling hasNext(), you probably have bigger problems.
If your hasNext() and next() calls aren't in a synchronized block/method, it is not guaranteed that you will have elements even if you call hasNext() before next().
The contract of the Iterator interface is that NoSuchElementException should be thrown if there are no more elements. So proceed with the next() method until such an exception arises.
That said, take a look at the java.util.concurrent package - it has concurrent collections whose iterators may help you - i.e. you can use these collections and iterators instead of implementing your own.
I would rather throw an exception from next(), when there are no more elements. In a multi-threaded environment hasNext() is pretty useless anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With