Design a site like this with WordPress.com
Get started

Java8 Streams – Convert List to Map

A lot of times we are required to convert one collection into another. It could be from list to set , set to map or otherwise. Before java introduced streams and functional programming, for doing such a transformation of collection was possible but then we had write a lot more code than we have to today with Java8 features.

Lets look at a simple example and transform a list to a map.

Lets say we have list of employee’s each having a name and id attribute. Our requirement is to convert the list into a map where key in the map is the “id” attribute of the employee and value is the employee object.

List<Employee> lstEmplyees = new ArrayList<>();
        lstEmplyees.add(new Employee(6606,"dipak"));
        lstEmplyees.add(new Employee(1212,"tony"));
        lstEmplyees.add(new Employee(779,"chetan"));

        Map<Integer,Employee> map =lstEmplyees.stream()
                                        .collect(Collectors.toMap(Employee::getId,Employee::get));
        System.out.println(map);

The above code creates a list 3 employee objects and then converts it into a map with help of streams.

Once you stream the collection, it provides us back with a stream of values in the list and then we can apply collect method to transform it into map. The collect method takes in Collector parameter, several of the implementations are already present in the “Collectors” class. For our use case we use Collectors.toMap. The toMap function takes two functions as input, first being the key mapper and second is the value mapper.

So as we know when we stream a collection, we are fed with stream of the objects inside the collection, one at a time.
In map function, we pass a function to identify the key from the employee object in our case. So for us it is the id attribute, so we return back the id attribute and the second parameter is the value function which return the value we want to associate with the streamed object.

Here is a simplified version of the above code

    List<Employee> lstEmplyees = new ArrayList<>();
        lstEmplyees.add(new Employee(6606,"dipak"));
        lstEmplyees.add(new Employee(1212,"tony"));
        lstEmplyees.add(new Employee(779,"chetan"));

        Function<Employee,Integer> keyMapper = (Employee employee) -> employee.getId();
        Function<Employee,Employee> valueMapper=  Function.identity();  // equvivaled to (Employee employee) -> employee;

        Map<Integer,Employee> map =lstEmplyees.stream()
                                        .collect(Collectors.toMap(keyMapper,valueMapper));
        System.out.println(map);

The above code works fine for just about any collection to convert to map. However, the above code will throw exception when there are duplicates in the collection. We haven’t told java what to do when there is a duplicate key. There is a third parameter that we can pass to tell java what do in case there is duplicate key.

The third parameter is the of the type – BinaryOperator which means it takes in 2 parameters of the same type and returns value of same type

Lets update our code to handle duplicates, in case of duplicates we want the new value to overwrite the old value.

List<Employee> lstEmplyees = new ArrayList<>();
        lstEmplyees.add(new Employee(6606,"dipak"));
        lstEmplyees.add(new Employee(1212,"tony"));
        lstEmplyees.add(new Employee(779,"chetan"));
        lstEmplyees.add(new Employee(779,"chetan1"));

        Function<Employee,Integer> keyMapper = (Employee employee) -> employee.getId();
        Function<Employee,Employee> valueMapper=  Function.identity();  // equvivaled to (Employee employee) -> employee;
        BinaryOperator<Employee> merge = (Employee oldVal,Employee newVal) -> newVal;

        Map<Integer,Employee> map =lstEmplyees.stream()
                                        .collect(Collectors.toMap(keyMapper,valueMapper));

Interesting to note here is that the merge function has parameter “Employee” instead of “Id attribute”. Its because the merge function is asking us to select the value to choose when there are duplicate keys.

There is one more variant of the “toMap” function. In the fourth parameter you can pass the map in which you would want to add the values.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: