Can the hasNext() iterator method return false first and then true?

3 weeks ago 29
ARTICLE AD BOX

The effective answer is: "No, you cannot do that". Or perhaps more accurately, "You should not do that".

Some parts of an API are explicitly checked by the compiler. A method definition in an interface can define that any implementation must, for example, return an int, and if you write an implementation that returns a String instead, it won't compile.

However, if that same API defines in its documentation that you must return a positive number, and you write return -1;, then the compiler will not stop you.

But there is no difference between these two situations. Both implementations are broken as written and should never be released. It's just the compiler so happens to be smart enough to catch one of them, and not smart enough to catch the other. If the compiler could be made that smart, it should be.

The same applies to your situation. What you're writing is an error, but one the compiler cannot catch. The semantic point of Iterator is not to return false first and true later.

Yes, you can, but that's just because the compiler can't detect you're writing a bug.

If you do, you need to think about your 'users'. You decided to implement Iterable for a reason. And that reason is that other code can call it, expecting a thing that acts like an implementation of Iterable, with all the bells and whistles. Everything explicitly required by the documentation of Iterable, and in rare cases, anything that isn't, but such a universally understood aspect, that most coders act as if it was part of the official spec. If you then return something that doesn't, that just leads to confusion.

Simple case in point:

for (String v : someIterableOfString) { System.out.println(v); }

would not do what you expected it to. It will deal with all elements until you first return false and then simply stop and continue with whatever code is below this loop. Whatever further data might eventually arrive simply won't ever get printed.

So what should you do

If you really want to do this, one option is that your hasNext() / next() methods will block. If you don't know if there will be another value or not, then.. simply wait until you do know. You should definitely document this; most folks don't expect an iterator to block, but that's only a light guide, and not a promise (such as 'once you return false, that's that' - that is a hard promise you should never break). For example, trivially, wrapping anything from disk can block, as can any database data.

You haven't given enough detail to meaningfully explain how one could 'block'. In essence, just "get" more data, and allow that process to block until it is available. Your next() should always invoke hasNext first, and hasNext, if there is no queued up data available, will do the 'okay then I will get it from the network' thing.

If your data stream never knows if it is done, that's a problem. You need to fix your data source then. Or simply implement hasNext() as return true;, if indeed it is endless.

That doesn't sound like it will fit

Then perhaps you shouldn't expose this via an iterable, but define something of your own design that doesn't have the implied baggage that Iterator does.

Read Entire Article