I’ve read that wonderful answer about the difference between map
and flatMap
.
And there is a picture that demonstrates flatmap:
And quote:
The map is for synchronous, non-blocking, one-to-one transformations while the flatMap is for asynchronous (non-blocking) One-to-Many transformations.
Based on that picture and quote I understand that flatMap
allows the creation of more (or fewer) elements than it was in the initial Flux
. But all examples I was able to find contains the same amount of element in the initial sequence after flatMap
like here:
Flux<Player> players = Flux.just("Zahid Khan", "Arif Khan", "Obaid Sheikh") .flatMap(fullname -> Mono .just(fullname) .map(p -> { String[] split = p.split("\s"); return new Player(split[0], split[1]); }) .subscribeOn(Scheduler.parallel()));
3 strings as input and 3 players as output:
List<Player> playerList = Arrays.asList( new Player("Zahid", "Khan"), new Player("Arif", "Khan"), new Player("Obaid", "Sheikh"));
My question is:
Is there a way to modify my example to achieve 3 strings as input and 6 (for example) players as output to prove that flatmap could be one-to-many?
Advertisement
Answer
“Many” does not necessarily lead to “more”. The term “one-to-many” is often shortened to 1:N
where N
stands for anything – it can be zero, one, or even ten.
In your example, you flatMap
each element into a single one (Mono.just(..)
+ Mono#map(..)
). There can be various numbers of items depending on implementation.
FlatMap as one to zero
The simplest example where flatMap
results in no element:
Flux.just("Zahid Khan", "Arif Khan", "Obaid Sheikh") .flatMap(fullName -> Mono.empty()) .subscribe(System.out::println);
FlatMap as one to one
This is exactly your example. I would simplify it a bit:
Flux.just("Zahid Khan", "Arif Khan", "Obaid Sheikh") .flatMap(fullName -> { String[] split = fullName.split("\s"); return Mono.just(new Player(split[0], split[1])); }) .subscribe(System.out::println);
Player(name=Zahid, surname=Khan) Player(name=Arif, surname=Khan) Player(name=Obaid, surname=Sheikh)
FlatMap as one to many (more than one)
In this case, we yield 2 players from each input (father and junior):
Flux.just("Zahid Khan", "Arif Khan", "Obaid Sheikh") .flatMap(fullName -> { String[] split = fullName.split("\s"); return Flux.just( new Player(split[0], split[1]), new Player(split[0], split[1] + " Jr.")); }) .subscribe(System.out::println);
Player(name=Zahid, surname=Khan) Player(name=Zahid, surname=Khan Jr.) Player(name=Arif, surname=Khan) Player(name=Arif, surname=Khan Jr.) Player(name=Obaid, surname=Sheikh) Player(name=Obaid, surname=Sheikh Jr.)