Core principles of spring cloud RPC: RxJava responsive programming framework, transformation operator

Posted by diddy1234 on Tue, 18 Jan 2022 19:18:56 +0100

Conversion operator

This section introduces three conversion operators of RxJava: map operator, flatMap operator and scan operator.

map operator

The map operator accepts a conversion function, applies the conversion function to each element in the message flow ejected by Observable, and the converted result pops up from the message flow. The message flow returned by the map operator consists of the result after the conversion function performs the conversion.

The processing flow of the map operator is shown in Figure 4-6.

Figure 4-6 processing flow of map operator

The map operator needs to receive an object of the functional interface function < T, R >, which implements the apply (T) method of the interface. This method is responsible for converting the received argument and returning the new value after conversion.

Examples of map operators are as follows:

package com.crazymaker.demo.rxJava.basic;
//Omit import
@Slf4j
public class TransformationDemo
{
 /**
*Demonstrate map conversion
*/
 @Test
 public void mapDemo() {
 Observable.range(1, 4)
 .map(i -> i *i)
 .subscribe(i -> log.info(i.toString()));
 }
...
}

Run the demo program, and the output results are as follows:

[main] INFO c.c.d.r.b.TransformationDemo - 1
[main] INFO c.c.d.r.b.TransformationDemo - 4
[main] INFO c.c.d.r.b.TransformationDemo - 9
[main] INFO c.c.d.r.b.TransformationDemo - 16

The map operator takes a value from the message flow and then returns another value. The conversion logic is one-to-one, which is not the logic of the flatMap operator.

flatMap operator

The flatMap operator packages any number of elements (zero or infinite items) of the input message flow into a new Observable topic and pops up.

The processing flow of flatMap operator is shown in Figure 4-7.

Figure 4-7 processing flow of flatmap operator

The flatMap operator changes the Observable flow of an ejection data into a new stream of ejection Observable subject objects. The subject objects (elements) popped up by the new stream will contain one or more data elements in the source stream. Its characteristics are as follows:

(1) flatMap conversion is one-to-one or one to many. Several data were ejected originally, and more data can be obtained after conversion.

(2) flatMap conversion can also change the data type of ejection.

(3) The data after flatMap conversion will still be transmitted to downstream subscribers one by one to receive. On the surface, it is like that these data are transmitted by one Observable. In fact, they are transmitted and combined by multiple observables. An example of a simple flatMap operator is as follows:

package com.crazymaker.demo.rxJava.basic;
//Omit import
@Slf4j
public class TransformationDemo
{
 ...
 /**
 *Demonstrate flapMap conversion
 */
 @Test
 public void flapMapDemo()
 {
 /**
 *Note that just in flatMap creates a new stream
 */
 Observable.range(1, 4)
 .flatMap(i -> Observable.just(i *i, i *i + 1))
 .subscribe(i -> log.info(i.toString()));
 }
}

Run this demo program and the output is as follows:

[main] INFO c.c.d.r.b.TransformationDemo - 1
[main] INFO c.c.d.r.b.TransformationDemo - 2
[main] INFO c.c.d.r.b.TransformationDemo - 4
[main] INFO c.c.d.r.b.TransformationDemo - 5
[main] INFO c.c.d.r.b.TransformationDemo - 9
[main] INFO c.c.d.r.b.TransformationDemo - 10
[main] INFO c.c.d.r.b.TransformationDemo - 16
[main] INFO c.c.d.r.b.TransformationDemo - 17

Because the flatMap operator creates a new Observable topic object during the conversion, it can be classified as a creation operator. An example of a more complex flatMap operator is as follows:

package com.crazymaker.demo.rxJava.basic;
//Omit import
@Slf4j
public class TransformationDemo
{
 ...
 /**
 *Demonstrate a slightly more complex flapMap transformation
 */
 @Test public void flapMapDemo2()
 {
 Observable.range(1, 4)
 .flatMap(i -> Observable.range(1, i).toList())
 .subscribe(list -> log.info(list.toString()));
 }
}

In this use case, flatMap transforms the elements of the input stream into a Observable object through the range creation operator, then calls the toList() method to convert it into a new Observable theme object that wrappers a single List element and pops up. Run the demo program, and the output results are as follows:

[main] INFO c.c.d.r.b.TransformationDemo - [1]
[main] INFO c.c.d.r.b.TransformationDemo - [1, 2]
[main] INFO c.c.d.r.b.TransformationDemo - [1, 2, 3]
[main] INFO c.c.d.r.b.TransformationDemo - [1, 2, 3, 4]

scan operator

The scan operator applies a cumulative function to each item of data in an Observable stream sequence, and then ejects the cumulative result of this function. In addition to the first item, the scan operator takes the cumulative result of the previous data item as the input of the next data item when applying the cumulative function, so the scan operator is a bit similar to a recursive operation.

Assume that the accumulation function is a simple accumulation function, and then scan the data stream sequence of 1 ~ 5 with the scan operator. Its execution flow is shown in Figure 4-8.

Figure 4-8 cumulative scanning of 1 ~ 5 data stream sequences using scan operator

Scan the data stream sequence of 1 ~ 5 with scan operator and accumulate with accumulation function. Refer to the following implementation code:

package com.crazymaker.demo.rxJava.basic;
//Omit import
@Slf4j
public class TransformationDemo
{
 /**Demonstrate scan operator scanning*/
 @Test
 public void scanDemo()
 {
 /**Define an accumulator accumulation function */
 Func2<Integer, Integer, Integer> accumulator = new Func2<Integer, Integer, Integer>()
 {
 @Override
 public Integer call(Integer input1, Integer input2)
 {
 log.info(" {} + {} = {} ", input1, input2, input1 + input2);
 return input1 + input2; }
 };
 /**
 *Stream scanning using scan
 */
 Observable.range(1, 5)
 .scan(accumulator)
 .subscribe(new Action1<Integer>()
 {
 @Override
 public void call(Integer sum)
 {
 log.info(" Cumulative result: {} ", sum);
 }
 });
 }
}

Run the above code, and the output results are as follows:

[main] INFO c.c.d.r.b.TransformationDemo - Cumulative result: 1
[main] INFO c.c.d.r.b.TransformationDemo - 1 + 2 = 3
[main] INFO c.c.d.r.b.TransformationDemo - Cumulative result: 3
[main] INFO c.c.d.r.b.TransformationDemo - 3 + 3 = 6
[main] INFO c.c.d.r.b.TransformationDemo - Cumulative result: 6
[main] INFO c.c.d.r.b.TransformationDemo - 6 + 4 = 10
[main] INFO c.c.d.r.b.TransformationDemo - Cumulative result: 10
[main] INFO c.c.d.r.b.TransformationDemo - 10 + 5 = 15
[main] INFO c.c.d.r.b.TransformationDemo - Cumulative result: 15

In the above example, the scan operator applies the accumulator accumulation function to the first item of data 1 ejected by the original Observable stream, and then ejects the result 1 of the accumulation function as the first item of data of the output stream; Next, it fills the first result together with the second item data 2 of the original Observable stream into the accumulator accumulation function, and then ejects the accumulation result 3 as the second item data of the output stream. The scan operator continues to repeat this process, accumulating the original stream until the cumulative result of its last data item is ejected from the output stream.

This article explains the core principles of spring cloud RPC remote call: RxJava responsive programming framework and conversion operators

  1. The next article will explain the core principles of spring cloud RPC remote call: RxJava responsive programming framework and aggregation operator;
  2. Friends who think the article is good can forward this article and pay attention to the Xiaobian;
  3. Thank you for your support!

Topics: Java Programming Android Programmer rxjava