Are there differences between Streams, Java Streams and Reactive Streams?
Streams and observables are often used interchangeably, but some say there is a difference between them. So what is it all about?
While I was researching observables on the net, I came across the term “stream” quite often and I wondered if observables and streams were simply two different words for the same thing or if there was a difference.
While trying to find an answer, I read a lot about “pull-based”, “push-based” and “Reactive Programming”. But all this confused me more than it enlightened me. Some said that Streams and Observables are completely different. Others use the words interchangeably. After a lot of digging through various online sources, I’ll summarize my final understanding of Streams and Observables here in this article.
If you’re in a hurry, you can scroll down a bit to “So where’s the difference between all these streams?”. But before we get to that part, I’ve provided some basic information about the Observer pattern and reactive programming to help you better understand the technical details.
The Observer Pattern
With the Observer Pattern, objects can subscribe to a subject and get informed, whenever there is an update in the subject. Essentially, the subject maintains a list of its observers and automatically notifies them when any state is changed.
To understand the observer pattern, imagine an online movie platform (like Netflix). You eagerly wait for your favorite movie to come out on netflix so you can watch it immediately.
- You could check Netflix every day to see if the movie is already online, but that would be a waste of time, since the movie wouldn’t be online for a long time.
- Netflix could also send an email to every user as soon as your favorite movie is online. You would be very happy about that, but most people would be annoyed by their full inbox.
- You could click the “notify me” button and sign up for movie news. That way, only you (and a few other users who clicked the button) are subscribed to receive a notification when the movie is online. This is an analogy for the observer pattern. The movie is the subject that can notify the subscribers and you (the user) are the observer.
Reactive Programming
Reactive programming means that you program using — and relying on — events, rather than based on the order of your lines of code (that would be imperative programming).
Usually, there are several events involved, occurring at indeterminate times. Some of these events may occur in the future, for example. The sequence of events that happen over time is called a “stream”.
Andre Staltz defines it like this (here on GitHub):
Reactive programming is programming with asynchronous data streams.
You can think of it like a meeting between the two friends Alice and Bob. Alice invites Bob for watching a movie and a pizza.
- Synchronous: Alice is finished with work. She goes to the restaurant, orders the pizza and waits until it is ready. After she gets the pizza, she picks up Bob and they go home to watch the movie.
- Asynchronous: Alice orders the pizza online while she is still at work. She calls Bob and invites him to come over. She goes home, has the pizza delivered, and starts eating it. She also starts watching the movie without waiting for Bob.
- Reactive: Alice orders the pizza online while still at work. She calls Bob and invites him to come over. She goes home and has the pizza delivered, but waits until Bob comes over so they can start eating the pizza and watching the movie. Here, Alice waits until all the asynchronous actions are complete, and then continues with other actions.
So where’s the difference between all these “streams”?
The term “stream” does not really say much. A stream is simply “a sequence of data elements made available over time” (source: wikipedia). So the word “stream” does not imply any technical details, just that there is data and we can use it over time. It is a generic term that applies to Java Streams, Observables and even Iterators.
In my research I read a lot that “streams are pull-based” but this something very specific for Java Streams. And the library XStream uses the word “stream” instead of “observable” simply because the creator prefers the word stream to observable (issue at GitHub).
So when people use the word “stream”, they can mean different things that differ in their technical details. They could be talking about either Java Streams or Observables or something else.
1. Java Streams
Java streams can only be used once and are pull-based. Pull and push are just two different protocols which describe how data producers communicate with consumers. The data-consumer can decide when it gets the data from the data-producer. JS functions are pull-based too. The function produces data and the function can be called, “pulling” a value out of the function.
This approach is synchronous, because when we want to pull a value it has to be available the time we pull it.
2. Observables
An observable is simply an object that has a function registerObserver(observer)
(or with different naming in RxJS: subscribe(observer)
).
This means, that the observable is the Subject
being observed/subscribed to (see in the observer pattern above). You can also put it into other words: The stream is the “observable” being observed.
You can subscribe to an observable (stream) and get updates on changes on the observable.
For example, in RxJS an observable is an instance of the Observable
type and it has the method subscribe(observer)
, which returns a subscription. (Important: RxJS has different types of observables and calls one of the types “Subject” — this is something RxJS-specific)
import { Observable } from 'rxjs';const observable = new Observable(subscriber => {
subscriber.next(1);
subscriber.next(2);
});observable.subscribe(result => console.log(result));
I think that this image (which looks quite the same as the image below) describes the differences between the synchronous vs the asynchronous world very good.
3. (Functional) Reactive Streams/Observable Streams/Observable Sequence
When someone is talking about reactive streams, reactive functional streams, observable streams or observable sequences they basically mean the same. With libraries like RxJS, XStream or RxJava you can introduce reactive programming (Rx is an acronym for “reactive extension”). Not many languages have built-in support for reactive streams, so those Rx-.. libraries help you with that. Since Java 9 there also exists the built-in Flow
interface, which lets you work with reactive streams natively.
In difference to the previously mentioned Java Streams, those Observable Streams are push-based. This means that the data-producer decides when the data-consumer (the subscriber) gets the data. This is an asynchronous approach, as the data-producer pushes the value to the consumers when it is available.
Conclusion
As the word “stream” does not have a special, definitive meaning in the software context, I would suggest to always differentiate between Java Streams and Observable Streams when talking about streams to prevent confusion.
The main differences between the most common streams are following:
- Java Streams: pull-based and synchronous
- Observable Streams: push-based and asynchronous
I hope I could clarify some views on streams and if you are interested in this topic I have some great resources for you: