How to re-use a variable in multiple Mono operators?
Asked Answered
C

4

5

Consider this code:

Mono.just(myVar)
    .flatMap(MyClass::heavyOperation)
    .flatMap(MyClass::anotherHeavyOperation)
    .flatMap(res -> doSomething(res, MyClass.heavyOperation(myVar)));

I don't want to call twice MyClass.heavyOperation(myVar) with the same input for the sake of performance.

How can I reuse the result of the second operation in the fourth one?

I want to do something like this, which is forbidden:

Object myObj;
Mono.just(myVar)
    .flatMap(var -> {
               myObj = MyClass.heavyOperation(var);                  
               return myObj;
               })
    .flatMap(MyClass::anotherHeavyOperation)
    .flatMap(res -> doSomething(res, myObj));
Carillonneur answered 16/4, 2019 at 8:54 Comment(0)
P
6

Probably the best solution is to put everything that uses myObj in the same pipeline step.

Like this:

Mono.just(myVar)
    .flatMap(MyClass::heavyOperation)
    .flatMap(myObj -> MyClass.anotherHeavyOperation(myObj)
        .flatMap(res -> doSomething(res, myObj)));

The step that uses myObj can in turn be de-composed into a number of smaller sub-pipelines, and the top level pipeline can also continue as normally.

This is the basis of monadic operations in functional languages!

Plead answered 16/4, 2019 at 9:33 Comment(0)
C
2

You can create a tuple in the second flat map:

Mono.just(myVar)
    .flatMap(MyClass::heavyOperation)
    .flatMap(x -> Tuples.of(x, MyClass.anotherHeavyOperation(myVar))
    .flatMap(res -> doSomething(res.getT2(), res.getT1()));
Calchas answered 16/4, 2019 at 9:4 Comment(0)
C
2

Consider keeping the scope:

Mono.just(myVar)
    .flatMap(var -> {
        Object myObj = MyClass.heavyOperation(var);                  
        return MyClass.anotherHeavyOperation(myObj)
            .flatMap(res -> doSomething(res, myObj));
    });
Chartreuse answered 16/4, 2019 at 9:21 Comment(0)
A
0

You could save Mono to variable and then just zip it again with Mono after anotherHeavyOperation.

var heavyOperation = Mono.just(myVar)
    .flatMap(MyClass::heavyOperation)
    .cache();

heavyOperation
   .flatMap(MyClass::anotherHeavyOperation)
   .zipWith(heavyOperation, (res, ho) -> doSomething(res, ho));
Antilebanon answered 16/4, 2019 at 9:0 Comment(2)
Although this answer is selected as the best answer, it is wrong and will do the heavy operation twice because it is cold. Please be aware of it.Chartreuse
@Chartreuse You're right, but cache will fix it :) Corrected my answer. Thanks for the remark.Belgae

© 2022 - 2024 — McMap. All rights reserved.