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