jon lee
jon lee

Reputation: 887

Java - How to convert Scala Stream to Java Stream?

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

Answers (3)

Xavier Guihot
Xavier Guihot

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

robbo
robbo

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

lyjackal
lyjackal

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

Related Questions