Collecting Stream Items into Map in Java

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 !!

Sourcecode on Github

Was this post helpful?

Join 7000+ Awesome Developers

Get the latest updates from industry, awesome resources, blog updates and much more.

* We do not spam !!

2 thoughts on “Collecting Stream Items into Map in Java”

  1. If you wish to create map from list by id, but list contains duplicates you can use Collectors.toMap with BinnaryOperator:

     
    public static void main (String[] args) {
      List<Employee> employeeList = Arrays.asList(
                    new Employee(1, "A", 100),
                    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(5, "C", 500),
                    new Employee(6, "C", 600));
    
    
            Map<Long, Employee> employeesMap = employeeList.stream()
                    .collect(Collectors.toMap(Employee::getId,
                            Function.identity(), (first, second) -> first));
    
            employeesMap.entrySet().forEach(System.out::println);
    } 
    

    The console output will be:

     
    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]
    
    Reply

Leave a Comment

HowToDoInJava

A blog about Java and related technologies, the best practices, algorithms, and interview questions.