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


#1

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)
)


#2

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


#3

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!


#4

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


#5

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!


#6

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


#7

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.


#8

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


#9

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).

#10

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).


#11

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.


#12

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