2

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?

2
  • It's not clear what you're asking. Which exactly type you have on Scala side, and which type you need on Java side? Commented Nov 25, 2015 at 16:22
  • Scala side is creating a Scala Stream, and on the Java side I need to convert this to a Java input/output stream, Commented Nov 25, 2015 at 18:00

3 Answers 3

6

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
Sign up to request clarification or add additional context in comments.

Comments

5

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

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.