Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: stream vs sequence - why multiple ways to do the same thing?

Is there a reason why there are multiple ways to do the same thing in Kotlin

val viaSequence = items.asSequence()
    .filter { it%2 == 0 }
    .map { it*2 }
    .toList()
println(viaSequence)

val viaIterable = items.asIterable()
    .filter { it%2 == 0 }
    .map { it*2 }
    .toList()
println(viaIterable)

val viaStream = items.stream()
    .filter { it%2 == 0 }
    .map { it*2 }
    .toList()
println(viaStream)

I know that the following code creates a list on every step, which adds load to the GC, and as such should be avoided:

items.filter { it%2 == 0 }.map { it*2 }
like image 839
user14381362 Avatar asked Dec 06 '25 10:12

user14381362


1 Answers

Streams come from Java, where there are no inline functions, so Streams are the only way to use these functional chains on a collection in Java. Kotlin can do them directly on Iterables, which is better for performance in many cases because intermediate Stream or Sequence objects don't need to be created.

Kotlin has Sequences as an alternative to Streams with these advantages:

  • They use null to represent missing items instead of Optional. Nullable values are easier to work with in Kotlin because of its null safety features. It's also better for performance to avoid wrapping all the items in the collection.
  • Some of the operators and aggregation functions are much more concise and avoid having to juggle generic types (compare Sequence.groupBy to Stream.collect).
  • There are more operators provided for Sequences, which result in performance advantages and simpler code by cutting out intermediate steps.
  • Many terminal operators are inline functions, so they omit the last wrapper that a Stream would need.
  • The sequence builder lets you create a complicated lazy sequence of items with simple sequential syntax in a coroutine. Very powerful.
  • They work back to Java 1.6. Streams require Java 8 or higher. This one is irrelevant for Kotlin 1.5 and higher since Kotlin now requires JDK 8 or higher.

The other answer mentions the advantages that Streams have.

In most cases it's best for performance and code clarity to directly use the Iterable inline operator functions rather than Sequences or Streams. Aside from when you're using the sequence builder for lazily generating items, I would default to picking Iterable operators, and only consider and experiment with Sequences if there is a performance bottleneck that needs to be optimized. More often than not, you'll probably find that you can't get the Sequence way of doing it to perform better than the Iterable operators anyway.

Nice article comparing them here.

like image 61
Tenfour04 Avatar answered Dec 10 '25 22:12

Tenfour04