Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Problem Solving Examples in RxJava

akarnokd edited this pageDec 10, 2018 ·3 revisions

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

There used to be a site called "Project Euler" that presented a series of mathematical computing conundrums (some fairly easy, others quite baffling) and challenged people to solve them. The first one was a sort of warm-up exercise:

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 withrange and thenfilter out those that are not a multiple either of 3 or of 5:

Java

Observable<Integer>threesAndFives =Observable.range(1,999).filter(e ->e %3 ==0 ||e %5 ==0);

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 (bymapping each value onto its appropriate multiple), making sure to only generating new multiples while they are less than 1000 (thetakeWhile operator will help here), and thenmerge these sets:

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

def threes=Observable.range(1,999).map({it*3}).takeWhile({it<1000});def fives=Observable.range(1,999).map({it*5}).takeWhile({it<1000});def threesAndFives=Observable.merge(threes, fives).distinct();

Don't forget thedistinct operator here, otherwise merge will duplicate numbers like 15 that are multiples of both 5 and 3.

Next, we want to sum up the numbers in the resulting sequence. If you have installed the optionalrxjava-math module, this is elementary: just use an operator likesumInteger orsumLong on thethreesAndFives 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 therxjava-math module emit boolean evaluations of the sequence; we want something that can emit a number. Thereduce operator will do the job:

Java

Single<Integer>summer =threesAndFives.reduce(0, (a,b) ->a +b);

Groovy

def summer= threesAndFives.reduce(0, {a,b-> a+b });

Here is howreduce gets the job done. It starts with 0 as a seed. Then, with each item thatthreesAndFives emits, it calls the closure{ a, b -> a+b }, passing it the current seed value asa and the emission asb. The closure adds these together and returns that sum, andreduce uses this returned value to overwrite its seed. WhenthreesAndFives completes,reduce emits the final value returned from the closure as its sole emission:

iterationseedemissionreduce
1033
2358
38614
466232169999233168
Finally, we want to see the result. This means we must [subscribe](Observable#onnext-oncompleted-and-onerror) to the Observable we have constructed:

Java

summer.subscribe(System.out::print);

Groovy

summer.subscribe({println(it);});

Generate the Fibonacci Sequence

How could you create an Observable that emitsthe Fibonacci sequence?

The most direct way would be to use thecreate 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

Observable<Integer>fibonacci =Observable.create(emitter -> {intf1 =0,f2 =1,f =1;while (!emitter.isDisposed()) {emitter.onNext(f);f =f1 +f2;f1 =f2;f2 =f;    }});

Groovy

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;  };});

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

Observable<Integer>fibonacci =Observable.fromArray(0)                  .repeat()                  .scan(newint[]{0,1}, (a,b) ->newint[]{a[1],a[0] +a[1]})                  .map(a ->a[1]);

Groovy

def fibonacci=Observable.from(0).repeat().scan([0,1], {a,b-> [a[1], a[0]+a[1]] }).map({it[1]});

It's a littlejanky. Let's walk through it:

TheObservable.from(0).repeat() creates an Observable that just emits a series of zeroes. This just serves as grist for the mill to keepscan operating. The wayscan usually behaves is that it operates on the emissions from an Observable, one at a time, accumulating the result of operations on each emission in some sort of register, which it emits as its own emissions. The way we're using it here, it ignores the emissions from the source Observable entirely, and simply uses these emissions as an excuse to transform and emit its register. That register gets[0,1] as a seed, and with each iteration changes the register from[a,b] to[b,a+b] and then emits this register.

This has the effect of emitting the following sequence of items:[0,1], [1,1], [1,2], [2,3], [3,5], [5,8]...

The second item in this array describes the Fibonacci sequence. We can usemap 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

fibonacci.take(15).subscribe(System.out::println);

Groovy

fibonnaci.take(15).subscribe({println(it)})];

Is there a less-janky way to do this? Thegenerate operator would avoid the silliness of creating an Observable that does nothing but turn the crank ofseed, but this operator is not yet part of RxJava. Perhaps you can think of a more elegant solution?

Copyright (c) 2016-present, RxJava Contributors.
Twitter @RxJava |Gitter @RxJava

Clone this wiki locally


[8]ページ先頭

©2009-2025 Movatter.jp