It cache the result of the previous steps of the Flux/Mono until the cache() method is called, check the output of this code to see it in action:
import reactor.core.publisher.Mono;
public class CacheExample {
    public static void main(String[] args) {
        var mono = Mono.fromCallable(() -> {
            System.out.println("Go!");
            return 5;
        })
        .map(i -> {
            System.out.println("Double!");
            return i * 2;
        });
        var cached = mono.cache();
        System.out.println("Using cached");
        System.out.println("1. " + cached.block());
        System.out.println("2. " + cached.block());
        System.out.println("3. " + cached.block());
        System.out.println("Using NOT cached");
        System.out.println("1. " + mono.block());
        System.out.println("2. " + mono.block());
        System.out.println("3. " + mono.block());
    }
}
output:
Using cached
Go!
Double!
1. 10
2. 10
3. 10
Using NOT cached
Go!
Double!
1. 10
Go!
Double!
2. 10
Go!
Double!
3. 10