The syntax of map method in java 8 is :
<R> Stream<R> map(Function<? super T,? extends R> mapper)
but i can use a lambda expression :
personList.stream().filter(p -> p.getPersonType().equals("student")).map(p -> new Student(p.getId(), p.getName())).collect(Collectors.toList());
How does the argument in map method equates to a Function datatype.Please help me understand this .
Thanks
Best Answer
The function Function<? super T,? extends R> mapper
of the map
method basically represents any function taking one parameter and returning a value so in this specific case the lambda p -> new Student(p.getId(), p.getName())
is a function taking a Person
p and returning a Student
hence fits into that perfectly.
To look at it another way, the lambda is equivalent to:
.map(new Function<Person, Student>() {@Overridepublic Student apply(Person p) {return new Student(p.getId(), p.getName());}})
You can write like this Function<Person,Student> function = p -> new Student(p.getId(), p.getName())
so as you see it is represent a function.
personList.stream().filter(p -> p.getPersonType().equals("student")).map(function::apply) // p -> function.apply(p).collect(Collectors.toList());
In the context of your Stream<Person>
(assuming personList
is a List<Person>
), the lambda expression p -> new Student(p.getId(), p.getName())
implements a functional interface that accepts a Person
instance (an element of your Stream
) and returns a Student
instance.
Hence it matches the Function<Person,Student>
functional interface, which is the interface required by the map()
method.
At runtime, the following lambda expression:
p -> new Student(p.getId(), p.getName())
will be represented by the class that implements Function<T, R>
interface.
An instance of this functional interface can be passed as a parameter to Stream.map(...)
method:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
In order to get a better understanding of how this works, one could replace a lambda with a good old anonymous class that implements the corresponding interface.
.map(p -> new Student(p.getId(), p.getName()))
is equivalent to:
.map(new Function<Person, Student>() {@Overridepublic Student apply(Person p) {return new Student(p.getId(), p.getName());}})
Same as @Ousmane D. but instead of this:
.map(new Function<Person, Student>() {@Overridepublic Student apply(Person p) {return new Student(p.getId(), p.getName());}})
Try this:
Function<Person, Student> f = p -> new Student(p.getId(), p.getName());
and use it inside your stream with .map(f)
.