Tuples are strongly typed collections of two or more elements and Reactor comes with them built in. Some operations such as zipWith, return reactive streams of Tuples.
Flux has an instance method zipWith(Publisher<? extends T2> source2)
which has a return type of Flux<Tuple2<T,T2>>
. It waits for both Fluxes (the initial flux and source2) to emit an element and then combines the two into a Tuple. There’s also static method Flux.zip which is overloaded to take from two to eight Publishers and zip them together.
Zipping is useful when you want to perform multiple operations that return reactive results (Flux or Mono).
Mono has two main flavors of zipping (which both have a return type of Mono<Tuple2<T,T2>>
):
-
zipWith(Mono<? extends T2> other) – Zips the current stream with another stream, giving the combination of each corresponding element in the form of Tuple2.
-
zipWhen(Function<T,Mono<? extends T2>> rightGenerator) – Zips the current Mono with another Mono, giving the combination of each corresponding element in the form of Tuple2, but only after the first stream’s operation has completed.
For example, given you have two methods which perform asynchronous operations Mono<Course> getCourse(Long id)
and Mono<Integer> getStudentCount(Course course), imagine you want to get the student count from the course Id you could do the following:
Mono<Integer> getStudentCount(Long id) {
return getCourse(id)
.zipWhen(course -> getStudentCount(course))
.map(tuple2 -> tuple2.getT2());
}
This is a simple example but you can imagine combining two different entities, or performing logic on them before returning, or calling another method which takes two arguments, and so on.