60

It seems that both Iterator and Stream are lazy and allow you to keep returning elements to your heart's content. What's the difference between the two?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ryeguy
  • 65,519
  • 58
  • 198
  • 260

2 Answers2

53

Stream memoises and Iterator does not. You can traverse the same Stream multiple times and get the same result each time. Iterator, on the other hand, can only be traversed once.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Walter Chang
  • 11,547
  • 2
  • 47
  • 36
  • 1
    With regards to the memoization - if I access the Nth element, is the access time O(1) or O(N)? – ryeguy Oct 07 '09 at 04:14
  • 7
    @ryeguy It's O(n) because Stream builds a linked list to cache element values. – Walter Chang Oct 07 '09 at 04:44
  • 1
    OK, so what's the difference between Stream and Iterable then? – Martin Konicek May 30 '11 at 22:30
  • 3
    Does it mean that in the case of an infinitely long stream, memory usage will keep on increasing since Stream memoises the result and never throw them away? – lolski Apr 10 '15 at 06:12
  • 2
    @lolski: Yes, that is the case if you somewhere have a reference to the *first cell* of the stream. If you on the other hand overwrite the reference to the first cell as you read more elements, then earlier elements will get garbage collected. So you have to be a little careful so you don't hold on the the first element when you work with large streams. – Lii Aug 07 '16 at 08:45
24

They are both constructs for accessing a current element, having a yet unknown list of remaining elements (the lazy tail).

Iterator is an imperative construct which you can only traverse once.

Stream is a functional construct. In theory you can traverse it multiple times (and as others mentioned, it won't recompute the already computed parts), but in practice because Streams are either infinite or very large (that is why you use it in the first place), holding reference to the full stream doesn't make much sense (you run into Out Of Memory pretty easy).

Generally it is safer to the mind to avoid plain Streams. Alternatives are using EphemeralStream of Scalaz which auto-forgets unreferred parts using weak references, or using Iteratees (see also here) or something similiar.

Community
  • 1
  • 1
ron
  • 9,262
  • 4
  • 40
  • 73
  • I'm curious: why EphemeralStream is not a default implementation? You can always reconstruct forgotten part from data lineage (its a functional language). This sounds like a big design flaw. – tribbloid May 08 '17 at 22:01