Hey, I can't really understand the difference betw...
# announcements
c
Hey, I can't really understand the difference between Iterator and Iterable. They both seem to perform the same function, so I want to ask: what's the difference between them and when to use which one?
e
an iterable provides iterators. an iterator is stateful.
this will print
1 2 3 1 2 3
, because each
for
loop gets a new iterator:
Copy code
val iterable = listOf(1, 2, 3)
for (i in iterable) { println(i) }
for (j in iterable) { println(j) }
b
If you are familiar with cold/hot pattern - iterable - cold, iterator - hot.
e
this will print
1 2 3
, because by the time the second loop runs, the iterator has been consumed to the end
Copy code
val iterable = listOf(1, 2, 3)
val iterator = iterable.iterator()
for (i in iterator) { println(i) }
for (j in iterator) { println(j) }
same distinction in Java, but they don't allow
for (... in ...)
to be used on raw iterators
c
Oh, I see, thanks!
t
in other words: Iterator allows you to iterate over some elements - usually only once Iterable can provide an Iterator (usually a new instance on each request) If you're "iterating over an Iterable", you're actually just calling its
iterator()
function and use the returned Iterator
My advice (there may be exceptions): Only use the Iterator if you actually need it (e.g. calling
hasNext()
and
next()
or working with mutable iterators). If you just want to iterate over something, use Iterable (or, Collection, List, Set, ..., whatever fits best)
n
if you want to make something iterable over (often just once) without involving a container, it's extremely easy to do via sequences
handy for certain kinds of things
t
Sequences are great. The interface is actually the same as Iterable, but the semantics are different (esp. when you build a processing chain)
e
there's other occasions to use iterators directly - if you wanted to implement
fun zip3(Iterable<T>, Iterable<U>, Iterable<V>): Iterable<Triple<T, U, V>>
for example - but it's pretty rare
n
It sucks how every function like that needs to be implemented twice
And in this case it's especially annoying because each argument could be either one
So it'll never feel that ergonomic. But I guess it all goes back to the sequence iterable divide