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?
CodePudding user response:
"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.)
CodePudding user response:
I would like to point one thing:
Difference between .map()
and .flatMap()
is quite simple:
.map()
is meant to map given object to another object (or to the same object, if you want just to change something within that object).
This operation is fully synchronous.
.flatMap()
is meant to create another Publisher (can either be Mono
or Flux
) with given object
Emissions from Publisher inside .flatMap()
will be "merged" with "main" sequence.
This operation is asynchronous
EDITED:
Examples of .flatMap()
that returns:
Mono ("one-to-one"):
Flux.just("Hello")
.flatMap(word -> Mono.just(word " world!")) // return Mono that produces another value
.subscribe(System.out::println);
Which will print the following output:
Hello world!
Flux: ("one-to-many"):
Flux.just("Hello", " world!")
.flatMap(word -> Flux.fromArray(word.split("(?!^)"))) // return Flux that produces the letters of the given word
.subscribe(System.out::println);
Which will print the following output:
H
e
l
l
o
w
o
r
l
d
!