what is the actual difference between map() and flatMap()?
hi guys. can smb help me out with
stream().map()
and stream().flatmap
? In the google i saw that flatmap
flattens smth. What does it even mean? Can smb explain? Thanks alot44 Replies
⌛
This post has been reserved for your question.
Hey @bambyzas! Please useTIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here./close
or theClose Post
button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.
To map() and flatMap(), you pass converters. Converting each item of the stream to something else, making the original stream a new stream where all is converted.
But with flatMap(), the converter has to convert to a stream of something. If you gave the same converter to just map(), that would result in a stream of streams of stuff, which isn't useful.
flatMap() applies the converter given, but flattens the result. Instead of giving out a stream of streams of stuff, it gives out just a stream of stuff.
-> with flatMap, one element becomes many
eg if you have a stream of “ab”, “cd” flatMapping it with a function that turns the string into their individual characters and returns a stream of them returns in the stream “a”, “b”, “c”, “d”
Yes, but to be more precise, 0 and 1 are also perfectly fine
can u guys give me an example?
if i have List<Vegetables> and i do flatmap on it. what would i get?
Well does a vegetable itself contain a list of some kind?
no. Vegetable is just a pojo
yeah, flatmap isn't really useful then
Lets say you have a list of users, and each user has a list of emails, then you can use flatmap
eg:
users.stream().flatMap(user -> user.getEmails().stream()).collect(Collectors.toList())
This will give you a list of all users' emailsok i did some improvements. lets say i ahve such case:
so now i can use flatmap, right? bc i have a list of lists?
yes
ok. thanks. but i dont understand what im doing wrong here
farmerList.stream().flatMap(farmer -> farmer.getVegetables());
If you are finished with your post, please close it.
If you are not, please ignore this message.
Note that you will not be able to send further messages here after this post have been closed but you will be able to create new posts.
check what flatmap wants
It wants a function that returns a stream
a collection (or a list) is not a stream
how do u know?
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
? extends Stream
doesnt it mean that Function takes two things? wildcard extending a type, and wildcard extending a stream?(idk what that even means)
No Function doesn't change, one return value with one parameter
Don't worry about the ? extends or ? super too much
Just ignore them for now
ok. so i have to provide a
mapper
for flatmap
function. And what is the data type of the mapper
? that whole Function<...
things is very confusing to read and understandIf you ignore the ? super and ? extends, it's basically
Function<T, Stream<R>>
That should be understandablenot very clearly tbh. i see that for this interface, if i want to write a lambda (for example) i need to comply to
apply
methodbut i dont understand how to comply to Function<T, Stream<R>>?
So basically, the T here, becomes the T from the flatmap parameter, the R becomes the Stream<R> from the flatmap parameter
I think you need some good generics/lambda/stream tutorials, becuase you asked the same questiosn yesterday about map
but i know how lambdas and generics work. and i can write needed lambda for
map
. but flatmap is a little bit more difficultWell, I'm doubtful about the generics part, because that's what you just asked 🙂
generics are used when u want ur method to be able to accept/return any type
Yeah but the whole ? super ? extends is a big part of generics
Basically what those mean:
? super means that whatever you're presenting needs to be that type, or any parent of it
? extends means that whatever you're presenting needs to be that type, or any subtype of it
upper and lower bounds
correct
See, you get it 🙂
not really. i cant put everything together into one place
basically:
? super something
means that the generic type accepts any parent class of something
, eg with something
being String, the generic bound ? super String
would accept either String itself, or CharSequence for example. Read: ? super X
means "i can assign a value with type X to a variable having that generic type"
? extends something
means that the generic type accepts any child class or something
, so in the exact other direction. ? extends X
means "i can assign a value of that type to a variable of type X"i have theoretical knowledge, but cant even write a lambda that complies to the needed functional interface
In flatMap they do that so that if you have a method that takes a charSequence as a parameter, I can apply that on a stream of strings, because a String is a CharSequence
That's the ? super
And the return value needs to be at least a Stream, and the types of that stream need to be at least what I want the flatMap operation to return
If I want it to return a Number, I can pass in a method that returns Integer, because Integer extends Number
That's the ? extends
if i use
map
, i ctrl-click on it, and see this: <R> Stream<R> map(Function<? super T, ? extends R> mapper);
and it basically means, that i need to provide a mapper
. its type is Function
that operates on two types. then i ctrl-click on function, and see R apply(T t);
. so it means that my lambda for .stream().map()
has to be smth like .map(farmer->farmer.getName())
.
but if i do .stream.flatMap()
now im stuck and cant write lambda in a similar manner. i ctrl-click on flatMap
and i get <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
. so it means that mapper
types is a Function
that operates on datatype and a stream. then again i ctr-click on Function
and see the same R apply (T t)
. and thats it. idk what to do next, because for mapper
i need a Function
with 2 args, and here i see that it can actually take only one.Where's the second arg?
the function args are the exact same
now your function accepts anything above T, and returns a stream of anything below R
same thing
So basically, the T here, becomes the T from the flatmap parameter, the R becomes the Stream<R> from the flatmap parameter
What I said here basically
this would be the logic?
yes
ok, but whose stream is it? where do i get it?
you make it
you make a new stream consisting of the elements you want to put into the stream
you convert one element to a stream of other elements, which are then "appended" to the current stream
or rather, the element you get as an argument is replaced with the elements in the stream you returned for that element
Collection and Optional have .stream()
Or you could roll your own
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.