Skip to content

#6323 Java 8 version for Problem-Solving-Examples-in-RxJava #6324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 10, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 56 additions & 6 deletions docs/Problem-Solving-Examples-in-RxJava.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
This page will present some elementary RxJava puzzles and walk through some solutions (using the Groovy language implementation of RxJava) as a way of introducing you to some of the RxJava operators.
This page will present some elementary RxJava puzzles and walk through some solutions as a way of introducing you to some of the RxJava operators.

# Project Euler problem #1

Expand All @@ -7,10 +7,22 @@ There used to be a site called "Project Euler" that presented a series of mathem
> If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000.

There are several ways we could go about this with RxJava. We might, for instance, begin by going through all of the natural numbers below 1000 with [`range`](Creating-Observables#range) and then [`filter`](Filtering-Observables#filter) out those that are not a multiple either of 3 or of 5:
### Java
```java
Observable<Integer> threesAndFives = Observable.range(1, 999).filter(e -> e % 3 == 0 || e % 5 == 0);
```
### Groovy
````groovy
def threesAndFives = Observable.range(1,999).filter({ !((it % 3) && (it % 5)) });
````
Or, we could generate two Observable sequences, one containing the multiples of three and the other containing the multiples of five (by [`map`](https://github.com/Netflix/RxJava/wiki/Transforming-Observables#map)ping each value onto its appropriate multiple), making sure to only generating new multiples while they are less than 1000 (the [`takeWhile`](Conditional-and-Boolean-Operators#takewhile-and-takewhilewithindex) operator will help here), and then [`merge`](Combining-Observables#merge) these sets:
### Java
```java
Observable<Integer> threes = Observable.range(1, 999).map(e -> e * 3).takeWhile(e -> e < 1000);
Observable<Integer> fives = Observable.range(1, 999).map(e -> e * 5).takeWhile(e -> e < 1000);
Observable<Integer> threesAndFives = Observable.merge(threes, fives).distinct();
```
### Groovy
````groovy
def threes = Observable.range(1,999).map({it*3}).takeWhile({it<1000});
def fives = Observable.range(1,999).map({it*5}).takeWhile({it<1000});
Expand All @@ -21,6 +33,11 @@ Don't forget the [`distinct`](Filtering-Observables#distinct) operator here, oth
Next, we want to sum up the numbers in the resulting sequence. If you have installed the optional `rxjava-math` module, this is elementary: just use an operator like [`sumInteger` or `sumLong`](Mathematical-and-Aggregate-Operators#suminteger-sumlong-sumfloat-and-sumdouble) on the `threesAndFives` Observable. But what if you don't have this module? How could you use standard RxJava operators to sum up a sequence and emit that sum?

There are a number of operators that reduce a sequence emitted by a source Observable to a single value emitted by the resulting Observable. Most of the ones that are not in the `rxjava-math` module emit boolean evaluations of the sequence; we want something that can emit a number. The [`reduce`](Mathematical-and-Aggregate-Operators#reduce) operator will do the job:
### Java
```java
Single<Integer> summer = threesAndFives.reduce(0, (a, b) -> a + b);
```
### Groovy
````groovy
def summer = threesAndFives.reduce(0, { a, b -> a+b });
````
Expand All @@ -38,6 +55,12 @@ Here is how `reduce` gets the job done. It starts with 0 as a seed. Then, with e
</tbody>
</table>
Finally, we want to see the result. This means we must [subscribe](Observable#onnext-oncompleted-and-onerror) to the Observable we have constructed:

### Java
```java
summer.subscribe(System.out::print);
```
### Groovy
````groovy
summer.subscribe({println(it);});
````
Expand All @@ -47,11 +70,24 @@ summer.subscribe({println(it);});
How could you create an Observable that emits [the Fibonacci sequence](http://en.wikipedia.org/wiki/Fibonacci_number)?

The most direct way would be to use the [`create`](Creating-Observables#wiki-create) operator to make an Observable "from scratch," and then use a traditional loop within the closure you pass to that operator to generate the sequence. Something like this:
### Java
```java
Observable<Integer> fibonacci = Observable.create(emitter -> {
int f1 = 0, f2 = 1, f = 1;
while (!emitter.isDisposed()) {
emitter.onNext(f);
f = f1 + f2;
f1 = f2;
f2 = f;
}
});
```
### Groovy
````groovy
def fibonacci = Observable.create({ observer ->
def f1=0; f2=1, f=1;
while(!observer.isUnsubscribed() {
observer.onNext(f);
def fibonacci = Observable.create({ emitter ->
def f1=0, f2=1, f=1;
while(!emitter.isDisposed()) {
emitter.onNext(f);
f = f1+f2;
f1 = f2;
f2 = f;
Expand All @@ -61,7 +97,16 @@ def fibonacci = Observable.create({ observer ->
But this is a little too much like ordinary linear programming. Is there some way we can instead create this sequence by composing together existing Observable operators?

Here's an option that does this:
````
### Java
```java
Observable<Integer> fibonacci =
Observable.fromArray(0)
.repeat()
.scan(new int[]{0, 1}, (a, b) -> new int[]{a[1], a[0] + a[1]})
.map(a -> a[1]);
```
### Groovy
````groovy
def fibonacci = Observable.from(0).repeat().scan([0,1], { a,b -> [a[1], a[0]+a[1]] }).map({it[1]});
````
It's a little [janky](http://www.urbandictionary.com/define.php?term=janky). Let's walk through it:
Expand All @@ -73,6 +118,11 @@ This has the effect of emitting the following sequence of items: `[0,1], [1,1],
The second item in this array describes the Fibonacci sequence. We can use `map` to reduce the sequence to just that item.

To print out a portion of this sequence (using either method), you would use code like the following:
### Java
```java
fibonacci.take(15).subscribe(System.out::println);
```
### Groovy
````groovy
fibonnaci.take(15).subscribe({println(it)})];
````
Expand Down