Learn to collect Stream items into Map using Collectors.toMap()
and Collectors.groupingBy()
methods using Java Stream APIs.
1. Collectors.toMap() for Unique Key-value Pairs
If the stream items have the unique map key field then we can use Collectors.toMap()
to collect items to Map in Map<keyObj, Item>
format.
For example, we can collect a list of Employee
objects to Map in where employee ids are unique fields and used as keys to the Map entries.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Main
{
public static void main(String[] args)
{
List<Employee> employeeList = new ArrayList<>(Arrays.asList(
new Employee(1, "A", 100),
new Employee(2, "A", 200),
new Employee(3, "B", 300),
new Employee(4, "B", 400),
new Employee(5, "C", 500),
new Employee(6, "C", 600)));
Map<Long, Employee> employeesMap = employeeList.stream()
.collect( Collectors.toMap(Employee::getId,
Function.identity()) );
System.out.println(employeesMap);
}
}
Program output.
{1=Employee [id=1, name=A, salary=100.0],
2=Employee [id=2, name=A, salary=200.0],
3=Employee [id=3, name=B, salary=300.0],
4=Employee [id=4, name=B, salary=400.0],
5=Employee [id=5, name=C, salary=500.0],
6=Employee [id=6, name=C, salary=600.0]}
2. Collectors.groupingBy() when Multiple Keys have Same Value
If the stream has items where Map keys are duplicate then we can use Collectors.groupingBy() to collect elements in Map<key, List<value>>
format. Here for each map key, we will store all elements in a List as the value.
For example, we can collect a list of Employee
objects to map in where employee names may be duplicate fields for some stream elements. In such a case, all employees with the same name will be stored in a List, and the list will be stored as Map value field.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main
{
public static void main(String[] args)
{
List<Employee> employeeList = new ArrayList<>(Arrays.asList(
new Employee(1, "A", 100),
new Employee(2, "A", 200),
new Employee(3, "B", 300),
new Employee(4, "B", 400),
new Employee(5, "C", 500),
new Employee(6, "C", 600)));
Map<String, List<Employee>> employeesMap = employeeList.stream()
.collect(Collectors.groupingBy(Employee::getName));
System.out.println(employeesMap);
}
}
Program output.
{A=[Employee [id=1, name=A, salary=100.0], Employee [id=2, name=A, salary=200.0]],
B=[Employee [id=3, name=B, salary=300.0], Employee [id=4, name=B, salary=400.0]],
C=[Employee [id=5, name=C, salary=500.0], Employee [id=6, name=C, salary=600.0]]}
3. Conclusion
It is very important to know beforehand if the Stream
elements will have a distinct value for the map key field or not.
If map keys are duplicate and we use Collectors.toMap()
method, we will get the IllegalStateException:
Exception in thread "main" java.lang.IllegalStateException: Duplicate key Employee [id=5, name=C, salary=500.0]
at java.util.stream.Collectors.lambda$throwingMerger$106(Collectors.java:133)
at java.util.stream.Collectors$$Lambda$3/149928006.apply(Unknown Source)
at java.util.HashMap.merge(HashMap.java:1245)
Happy Learning !!
Leave a Reply