Why is Iterable<T>.stream() extension function not included in the standard library

Hi,

Implementation would be

 fun <T> Iterable<T>.stream(): Stream<T> =
    StreamSupport.stream(spliterator(), false)

Thanks for your explanations.
(The same is true for:
fun <T> Array<T>.stream() = Arrays.stream(this)
)

Kotlin implements Iterable<T>.asSequence() which is virtually the same as the Java 8 Collection<T>.stream()

But if you really need to use the Java 8 Stream, you can do the following:

import java.util.stream.Stream
import kotlin.streams.asStream

fun main(args: Array<String>) {
    val iterable: Iterable<String> = listOf("Hello", "World")
    val stream: Stream<String> = iterable.asSequence().asStream()
}

NOTE: To use the Sequence<T>.asStream() you will need, at least, Kotlin 1.2 and Java 8

2 Likes

So a Sequence is preferred to a Stream in Kotlin and it has not a to big influence on performance? (Especially with many map operations chained)

Thanks for your answer!

I do not really know how better is one over the other, but I made a quick test to give you an idea:

  • 100000 randomly generated integers using Random().nextInt().
  • 7 chained .map() operations, and a .sum() at the end
  • Test run 1000 times for each implementation (Sequence and Stream)

The results:

Java 8 Stream:
    Avg: 13.5627 ms
    Min: 12.0088 ms
    Max: 60.8363 ms

Kotlin Sequence:
    Avg: 14.8622 ms
    Min: 13.9806 ms
    Max: 34.5802 ms

Note: The tests were run on an i7-4720HQ with 16GB of RAM

Thank you!

That’s a good number, I was unsure about that.

I guess you used Stream and not IntStream.

I am more than happy with the results and slowly switch to Sequence!

Correct, I used Stream<Int> and Sequence<Int>

You don’t need to do all this, you just need to use the java 8 version of the standard library: https://kotlinlang.org/docs/reference/whatsnew11.html#java-8-standard-library-support

This will make streams available (but of course not for older Android versions). If you don’t need the parallelism or Java compatibility you should probably consider Kotlin Sequences thought.

Just because I stumbled over this question again, @pdvrieze, the Iterable.stream is not part of the Standard Library, even if I download the J8 support. Hoever, this is not a bug deal, thanks to Kotlin you can fix such things for yourself within seconds.

Yours,

Florian

stdlib-jdk9 contains methods to convert sequences into stream. Kotlin encourages to work with sequences instead of streams and most cases it is indeed good.
I can see only two points, where streams could be better:

  1. Stream automatic parallel processing is much easier that coroutine analog to implement.
  2. Stream actually use invokeDynamic directive, which probably increases performance (maybe, I have not found actual tests).

I did a test, at the beginning of the year and Kotlin couroutines are really, really faster than parallel stream specially when there is blocking issue (the factor was something like 6 or 7 times on a blocking program).

It is the case when you are using large number of very light operations, in case of small number of very heavy computations, coroutine context switching overhead could be significant.

Thx, I ignored it. My program was just a test program with random wait (an operation duration was around 1000ms).