Skip to content

Commit

Permalink
#6323 Java 8 version for Problem-Solving-Examples-in-RxJava (#6324)
Browse files Browse the repository at this point in the history
* #6323 Java 8 version for Project Euler problem

* #6323 Java 8 version for Generate the Fibonacci Sequence

* #6323 Java 8 version for Project Euler problem
 - Fix name of variable

* #6324 Fixing for code review.
  • Loading branch information
hoangnam2261 authored and akarnokd committed Dec 10, 2018
1 parent 6ae765a commit bc40695
Showing 1 changed file with 56 additions and 6 deletions.
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

0 comments on commit bc40695

Please sign in to comment.