Java 8 – How to use Collectors.mapping Collector with examples
This tutorial explains how to use Java 8's predefined collector returned by
Where,
- 1st input parameter is
- 2nd input parameter is
- output is a
So, when you have a
When mapping collector is used to collect elements of a
To complete our understanding of how the mapping collector works, let us see couple of Java 8 code examples which show show to use the collector in code.
OUTPUT of the above code
Explanation of the code
(Note - The
OUTPUT of the above code
Explanation of the code
Collectors.mapping()
method with examples. It first explains the definition of the static mapping()
method, followed by a quick explanation of its working, and then shows how to use Collector returned by Collectors.mapping()
using two Java 8 code examples.
Collectors.mapping() method
Collectors.mapping()
method is defined with the following signature - public static <T, U, A, R> Collector<T, ?, R>
mapping(Function<? super T,? extends U> mapper,Collector<? super U,A,R> downstream)
- 1st input parameter is
mapper
an instance of FunctionClick to Read Tutorial on Function Functional Interface functional interface, which converts stream elements of type T
to type U
- 2nd input parameter is
downstream
an instance of a standard collectorClick to Read Tutorial on Collector basics which collects elements of type U
in the result type R
- output is a
Collector
which collects elements of type T
in the result type R
.
How the Collector returned by Collectors.mapping() method works
The collector returned by Collector.mapping()
method acts as an adapterClick to Read Tutorial on Adapter Design Pattern which allows a collector to accept a type T
, instead of the type for which it was built, i.e. U
. The collector works by applying a mapping function from T
to U
which is passed to the Collector.mapping()
method as the first parameter(refer collector method signature above for more context on type T
& U
).Collector<U,A,R>
which can process elements of type U
, but you need instead a Collector<T,A,R>
, then you can use the mapping collector to adapt your Collector<U,A,R>
using a Function<T,U>
. When mapping collector is used to collect elements of a
Stream<T>
, it first maps/transforms/converts the stream elements of type T
to type U
using Function<T,U>
, and then collects them using Collector<U,A,R>
, in effect allowing your collector which accepts Stream<U>
to now work with(or adapt to) Stream<T>
.To complete our understanding of how the mapping collector works, let us see couple of Java 8 code examples which show show to use the collector in code.
Example 1 - Java 8 Code showing Collectors.mapping() usage
//MappingCollector.java
package com.javabrahman.java8.collector;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class MappingCollector {
static List<Employee> employeeList
= Arrays.asList(new Employee("Tom Jones", 45, 15000.00),
new Employee("Harry Andrews", 45, 7000.00),
new Employee("Ethan Hardy", 65, 8000.00),
new Employee("Nancy Smith", 22, 10000.00),
new Employee("Deborah Sprightly", 29, 9000.00));
public static void main(String[] args) {
List<String> employeeNames = employeeList
.stream()
.collect(Collectors.mapping(Employee::getName, Collectors.toList()));
System.out.println("List of employee names:" + employeeNames);
}
}
//Employee.java(POJO class)
package com.javabrahman.java8.collector;
public class Employee {
private String name;
private Integer age;
private Double salary;
public Employee(String name, Integer age, Double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
//Setters and Getters for name, age & salary go here
public String toString(){
return "Name: "+ this.name
+ " Age: "+ this.age;
}
//Standard implementations for overridden hashcode() & equals() goes here
}
Set of employee names:[Tom Jones, Harry Andrews, Ethan Hardy, Nancy Smith, Deborah Sprightly]
MappingCollector
class contains a static list ofEmployee
objects -employeeList
.- In the
main()
method a stream ofEmployee
objects is created usingList.stream()
method. - Stream of employees is then pipelined to the
collect()
terminal operationClick to Read Tutorial explaining intermediate & terminal Stream operations. - To the
collect()
method,Collector
returned byCollectors.mapping()
method is passed as a parameter. - Mapping collector is invoked with the first input parameter(mapper function) as “
Employee::getName
”, which is a method referenceClick to Read Tutorial on Java 8's Method References, to theEmployee.getName()
method. For the second input parameter(downstream collector)- collector returned byCollectors.toList()
is passed. - Mapping collector then works in 2 steps. In the 1st step, it uses the mapper function to convert
Stream<Employee>
(stream of Employee objects) to an equivalentStream<String>
(stream of Employee names). In the 2nd step, the downstream collector is used to collect all employee names in aList<String>
instance. - Collected
List
is assigned to aList<String>
variable namedemployeeNames
, and printed. As expected, names of the 5 employees are printed as list content.
Employee
class and employeeList
objects with their values remain the same as the previous code usage example and hence are not shown again in example 2 below for brevity.)Example 2 - Collectors.mapping() in action
public static void main(String[] args) {
Optional<Integer> maxAge = employeeList
.stream()
.collect(Collectors.mapping((Employee emp) -> emp.getAge(), Collectors.maxBy(Integer::compareTo)));
System.out.println("Max Age: " + maxAge.get());
}
Max Age: 65
- The
Employee
objects in the stream are collected, with the inputs this time being method reference toEmployee
’sgetAge()
method(as mapper function), and Collectors.maxBy()Click to Read tutorial on maxBy()/minBy() collectors(as downstream collector) withInteger
’s natural comparison order being used as it's comparatorClick to Read in-depth tutorial on Java 8 Comparators’s sorting logic. - Mapping collector then works in 2 steps. In the 1st step, it uses the mapper function to convert
Stream<Employee>
(stream ofEmployee
objects) to an equivalentStream<Integer>
(stream of employee ages). In the 2nd step, the downstream collector is used to find the maximum age of among all employees. - Value of maximum age determined is assigned to an
Optional<Integer>
variable namedmaxAge
, and printed. As expected, the maximum age is printed as65
.
Java 8 Collectors' Tutorials on JavaBrahman
Understanding Basics of Java 8 CollectorsClick to Read Tutorial explaining basics of Java 8 CollectorsCollectors.groupingBy()Click to Read Tutorial on Grouping with CollectorsCollectors.partitioningBy()Click to Read Partitioning using Collectors TutorialCollectors.counting()Click to Read Counting with Collectors Tutorial Collectors.maxBy()/minBy()Click to Read Tutorial on finding max/min with CollectorsCollectors.joining()Click to Read Tutorial on joining as a String using CollectorsCollectors.collectingAndThen()Click to Read Tutorial on collectingAndThen CollectorCollectors.averagingInt() /averagingLong() /averagingDouble()Click to Read Tutorial on Averaging CollectorCollectors.toCollection()Click to Read Tutorial on Collectors.toCollection CollectorCollectors.mapping()Click to Read Tutorial on Mapping Collector
Understanding Basics of Java 8 CollectorsClick to Read Tutorial explaining basics of Java 8 CollectorsCollectors.groupingBy()Click to Read Tutorial on Grouping with CollectorsCollectors.partitioningBy()Click to Read Partitioning using Collectors TutorialCollectors.counting()Click to Read Counting with Collectors Tutorial Collectors.maxBy()/minBy()Click to Read Tutorial on finding max/min with CollectorsCollectors.joining()Click to Read Tutorial on joining as a String using CollectorsCollectors.collectingAndThen()Click to Read Tutorial on collectingAndThen CollectorCollectors.averagingInt() /averagingLong() /averagingDouble()Click to Read Tutorial on Averaging CollectorCollectors.toCollection()Click to Read Tutorial on Collectors.toCollection CollectorCollectors.mapping()Click to Read Tutorial on Mapping Collector