views:

79

answers:

5

If all that you're doing is a simple one-pass iteration (i.e. only hasNext() and next(), no remove()), are you guaranteed linear time performance and/or amortized constant cost per operation?

Is this specified in the Iterator contract anywhere?

Are there data structures/Java Collection which cannot be iterated in linear time?

java.util.Scanner implements Iterator<String>. A Scanner is hardly a data structure (e.g. remove() makes absolutely no sense). Is this considered a design blunder?

Is something like PrimeGenerator implements Iterator<Integer> considered bad design, or is this exactly what Iterator is for? (hasNext() always returns true, next() computes the next number on demand, remove() makes no sense).

Similarly, would it have made sense for java.util.Random implements Iterator<Double>?

Should a type really implement Iterator if it's effectively only using one-third of its API? (i.e. no remove(), always hasNext())

+7  A: 

There is no such guarantee. As you point out, anyone can model anything as Iterator. Individual producers of iterators would have to specify their individual performance.

bmargulies
less words = better ;-)
Joachim Sauer
+3  A: 

Nothing in the Iterator documentaton mentions any kind of performance guarantee, so there is no guarantee.

It also wouldn't make sense to require this constraint on such a universal tool.

A much more useful constraint would be document a iterator() method to specify the time constraints that this Iterator instance fulfills (for example an Iterator over a general-purpose Collection will most likely be able to guarantee linear time operation).

Similarly, nothing in the documentation requires hasNext() to ever return false, so an endless Iterator would be perfectly valid.

However, there is a general assumption that all Iterator instances behave like "normal" Iterator instances as returned by Collection.iterator() in that they return some number of values and end at some point. This is not required by the documentation and, strictly speaking, any code depending on that fact would be subtly broken.

Joachim Sauer
+1  A: 

All of your proposals sound reasonable for Iterator. The API docs explicitly say remove need not be supported, and suggests that one not use the older Enumeration that works just like Iterator except without remove.

Also, infinite-length streams are a very useful concept in functional programming, and can be implemented with an Iterator that always hasNext. It's a feature that it can handle either case.

Rex Kerr
A: 

I can imagine a use case for this.. And it seems intuitive enough. Personally I think it's fine.

for(long prime : new PrimeGenerator()){
    //do stuff
    if(condition){
        break;
    }
}
Enno Shioji
not to mention that if(condition) *could* be represented in hasNext anyway - it just may be more convenient to code it as you have.
Carl
+1  A: 

It sounds like you're thinking of iterators in the sense of a list or set traversal. I think a more useful mental model is a discrete object stream, aything that you want to handle one-at-a-time that can be streamed from a source in terms of discrete instances.

In that sense a stream of prime numbers or of list objects both makes sense, and the model doesn't imply anything about the finite-ness of the data source.

Steve B.