Are Java 8 streams similar to RxJava observables?
Java 8 stream definition:
Classes in the new
java.util.stream
package provide a Stream API to support functional-style operations on streams of elements.
All sequence/stream processing libs are offering very similar API for pipeline building. The differences are in API for handling multi-threading and composition of pipelines.
RxJava is quite different from Stream. Of all JDK things, the closest to rx.Observable
is perhaps java.util.stream.Collector
Stream
+ CompletableFuture
combo (which comes at a cost of dealing with extra monad layer, i. e. having to handle conversion between Stream<CompletableFuture<T>>
and CompletableFuture<Stream<T>>
).
There are significant differences between Observable and Stream:
Stream#parallel()
splits sequence into partitions, Observable#subscribeOn()
and Observable#observeOn()
do not; it is tricky to emulate Stream#parallel()
behavior with Observable, it once had .parallel()
method but this method caused so much confusion that .parallel()
support was moved to separate repository: ReactiveX/RxJavaParallel: Experimental Parallel Extensions for RxJava. More details are in another answer.Stream#parallel()
does not allow to specify a thread pool to use, unlike most of RxJava methods accepting optional Scheduler. Since all stream instances in a JVM use the same fork-join pool, adding .parallel()
can accidentally affect the behaviour in another module of your program.Observable#interval()
, Observable#window()
and many others; this is mostly because Streams are pull-based, and upstream has no control on when to emit next element downstream.takeWhile()
, takeUntil()
); workaround using Stream#anyMatch()
is limited: it is terminal operation, so you can't use it more than once per streamStream#zip()
operation, which is quite useful sometimes.Files#lines()
and BufferedReader#lines()
out of the box though, and other similar scenarios can be managed by constructing Stream from Iterator).Observable#using()
); you can wrap IO stream or mutex with it and be sure that the user will not forget to free the resource - it will be disposed automatically on subscription termination; Stream has onClose(Runnable)
method, but you have to call it manually or via try-with-resources. E. g. you have to keep in mind that Files#lines()
must be enclosed in try-with-resources block.RxJava differs from Streams significantly. Real RxJava alternatives are other implementations of ReactiveStreams, e. g. relevant part of Akka.
There's trick to use non-default fork-join pool for Stream#parallel
, see Custom thread pool in Java 8 parallel stream.
All of the above is based on the experience with RxJava 1.x. Now that RxJava 2.x is here, this answer may be out-of-date.