Is an "infinite" iterator bad design? [closed]

Solution 1:

I think it is entirely legitimate - an Iterator is just a stream of "stuff". Why should the stream necessarily be bounded?

Plenty of other languages (e.g. Scala) have the concept of unbounded streams built in to them and these can be iterated over. For example, using scalaz

scala> val fibs = (0, 1).iterate[Stream](t2 => t2._2 -> (t2._1 + t2._2)).map(_._1).iterator
fibs: Iterator[Int] = non-empty iterator

scala> fibs.take(10).mkString(", ") //first 10 fibonnacci numbers
res0: String = 0, 1, 1, 2, 3, 5, 8, 13, 21, 34

EDIT: In terms of the principle of least surprise, I think it depends entirely on the context. For example, what would I expect this method to return?

public Iterator<Integer> fibonacciSequence();

Solution 2:

The whole point of an Iterator is that it is lazy, i.e. that it gives you only as many objects as you ask for. If a user asks for all objects of an infinite Iterator, it's their problem, not yours.

Solution 3:

While I too think that it's legitimate, I'd like to add that such an Iterator (or more precisely: an Iterable producing such an Iterator) would not play well with the enhanced for-loop (a.k.a for-each-loop):

for (Object o : myIterable) {
   ...
}

Since the code inside an enhanced for loop has no direct access to the iterator, it couldn't call remove() on the iterator.

So to end the looping it would have to do one of the following:

  • Get access to the internal List of the Iterator and remove objects directly, possibly provoking a ConcurrentModificationException
  • use break to exit the loop
  • "use" an Exception to exit the loop
  • use return to leave the loop

All but the last of those alternatives aren't exactly the best way to leave an enhanced for-loop.

The "normal" for-loop (or any other loop together with an explicit Iterator variable) would work just fine, of course:

for (Iterator it = getIterator(); it.hasNext();) {
  Object o = it.next()
  ...
}

Solution 4:

This may be semantics, but the iterator should diligently return the next item without regard to when it will end. Ending is a side effect for a collection, though it may seem like a common side effect.

Still, what's the difference between infinite, and a collection with 10 trillion items? The caller either wants them all, or he doesn't. Let the caller decide how many items to return or when to end.

I wouldn't say the caller couldn't use the for-each construct. He could, as long as he wants all the items.

Something in the documentation for the collection like "may be an infinite collection" would be appropriate, but not "infinite iterator".

Solution 5:

It is a perfectly legitimate use - as long as it is properly documented.

Using the name CyclicIterator is a good idea, as it infers that looping on the iterator might well possibly be infinite if the loop exit case is not properly defined.