Reputation: 887
I have a Java application that receives a Scala Stream
.
I need to convert this to a Java Stream
.
How can I do this in Java?
Upvotes: 2
Views: 2600
Reputation: 61666
Starting Scala 2.13
, the standard library includes scala.jdk.javaapi.StreamConverters
which provides Java to Scala implicit stream conversions:
import scala.jdk.javaapi.StreamConverters;
// val scalaStream = Stream(1, 2, 3)
StreamConverters.asJavaSeqStream(scalaStream);
// java.util.stream.Stream[Int] = java.util.stream.ReferencePipeline$Head@3cccf515
Note that Stream
s are renamed LazyList
in Scala 2.13, in which case:
// val scalaLazyList = LazyList(1, 2, 3)
StreamConverters.asJavaSeqStream(scalaLazyList);
// java.util.stream.Stream[Int] = java.util.stream.ReferencePipeline$Head@4997c13
Upvotes: 6
Reputation: 51
If you don't want to process the stream in parallel you can simply subclass AbstractSpliterator:
import java.util.function.Consumer
import java.util.stream.StreamSupport
import java.util.{Spliterator, Spliterators}
def streamToJava[T](s: Stream[T]): java.util.stream.Stream[T] = {
var ss: Stream[T] = s
val splitr = new Spliterators.AbstractSpliterator[T](Long.MaxValue, Spliterator.IMMUTABLE) {
override def tryAdvance(action: Consumer[_ >: T]): Boolean = ss match {
case Stream.Empty => false
case h #:: tl => {ss = tl; action.accept(h); true}
}
}
StreamSupport.stream(splitr, false)
}
The other answer (I'm too new to comment) is incorrect as it calls size which materialises the entire stream.
Upvotes: 0
Reputation: 3984
This is a bit of a long way around, but you can convert the scala stream to an iterable, to a java iterable, then construct the java stream from the java iterable:
scala>
import java.util.stream.StreamSupport
import scala.collection.JavaConverters._
def stream2javaStream[T](scalaStream: scala.Stream[T]): java.util.stream.Stream[T] = {
StreamSupport.stream(scalaStream.toIterable.asJava.spliterator(), false);
}
stream2javaStream((1 to 100).toStream)
res0: java.util.stream.Stream[Int] = java.util.stream.ReferencePipeline$Head@2489e84a
While roundabout, this does not "realize" the stream, maintaining its efficiency.
scala>
stream2javaStream((1 to 100).toStream.map{i => println(i); i})
1
res1: java.util.stream.Stream[Int] = java.util.stream.ReferencePipeline$Head@9b21bd3
only prints 1 for the head of the stream
Upvotes: 5