Main Tutorials

Java 8 – Convert List to Map

Few Java 8 examples to show you how to convert a List of objects into a Map, and how to handle the duplicated keys.

Hosting.java

package com.mkyong.java8

public class Hosting {

    private int Id;
    private String name;
    private long websites;

    public Hosting(int id, String name, long websites) {
        Id = id;
        this.name = name;
        this.websites = websites;
    }

    //getters, setters and toString()
}

1. List to Map – Collectors.toMap()

Create a list of the Hosting objects, and uses Collectors.toMap to convert it into a Map.

TestListMap.java

package com.mkyong.java8

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TestListMap {

    public static void main(String[] args) {

        List<Hosting> list = new ArrayList<>();
        list.add(new Hosting(1, "liquidweb.com", 80000));
        list.add(new Hosting(2, "linode.com", 90000));
        list.add(new Hosting(3, "digitalocean.com", 120000));
        list.add(new Hosting(4, "aws.amazon.com", 200000));
        list.add(new Hosting(5, "mkyong.com", 1));

        // key = id, value - websites
        Map<Integer, String> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getId, Hosting::getName));

        System.out.println("Result 1 : " + result1);

        // key = name, value - websites
        Map<String, Long> result2 = list.stream().collect(
                Collectors.toMap(Hosting::getName, Hosting::getWebsites));

        System.out.println("Result 2 : " + result2);

        // Same with result1, just different syntax
        // key = id, value = name
        Map<Integer, String> result3 = list.stream().collect(
                Collectors.toMap(x -> x.getId(), x -> x.getName()));

        System.out.println("Result 3 : " + result3);
    }
}

Output


Result 1 : {1=liquidweb.com, 2=linode.com, 3=digitalocean.com, 4=aws.amazon.com, 5=mkyong.com}
Result 2 : {liquidweb.com=80000, mkyong.com=1, digitalocean.com=120000, aws.amazon.com=200000, linode.com=90000}
Result 3 : {1=liquidweb.com, 2=linode.com, 3=digitalocean.com, 4=aws.amazon.com, 5=mkyong.com}

2. List to Map – Duplicated Key!

2.1 Run below code, and duplicated key errors will be thrown!

TestDuplicatedKey.java

package com.mkyong.java8;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TestDuplicatedKey {

    public static void main(String[] args) {

        List<Hosting> list = new ArrayList<>();
        list.add(new Hosting(1, "liquidweb.com", 80000));
        list.add(new Hosting(2, "linode.com", 90000));
        list.add(new Hosting(3, "digitalocean.com", 120000));
        list.add(new Hosting(4, "aws.amazon.com", 200000));
        list.add(new Hosting(5, "mkyong.com", 1));
		
        list.add(new Hosting(6, "linode.com", 100000)); // new line

        // key = name, value - websites , but the key 'linode' is duplicated!?
        Map<String, Long> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getName, Hosting::getWebsites));

        System.out.println("Result 1 : " + result1);

    }
}

Output – The error message below is a bit misleading, it should show “linode” instead of the value of the key.


Exception in thread "main" java.lang.IllegalStateException: Duplicate key 90000
	at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
	at java.util.HashMap.merge(HashMap.java:1245)
	//...

2.2 To solve the duplicated key issue above, pass in the third mergeFunction argument like this :


	Map<String, Long> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getName, Hosting::getWebsites,
                        (oldValue, newValue) -> oldValue
                )
        );

Output


Result 1 : {..., aws.amazon.com=200000, linode.com=90000}
Note
(oldValue, newValue) -> oldValue ==> If the key is duplicated, do you prefer oldKey or newKey?

3.3 Try newValue


	Map<String, Long> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getName, Hosting::getWebsites,
                        (oldValue, newValue) -> newvalue
                )
        );

Output


Result 1 : {..., aws.amazon.com=200000, linode.com=100000}

3. List to Map – Sort & Collect

TestSortCollect.java

package com.mkyong.java8;

import java.util.*;
import java.util.stream.Collectors;

public class TestSortCollect {

    public static void main(String[] args) {

        List<Hosting> list = new ArrayList<>();
        list.add(new Hosting(1, "liquidweb.com", 80000));
        list.add(new Hosting(2, "linode.com", 90000));
        list.add(new Hosting(3, "digitalocean.com", 120000));
        list.add(new Hosting(4, "aws.amazon.com", 200000));
        list.add(new Hosting(5, "mkyong.com", 1));
        list.add(new Hosting(6, "linode.com", 100000));

        //example 1
        Map result1 = list.stream()
                .sorted(Comparator.comparingLong(Hosting::getWebsites).reversed())
                .collect(
                        Collectors.toMap(
                                Hosting::getName, Hosting::getWebsites, // key = name, value = websites
                                (oldValue, newValue) -> oldValue,       // if same key, take the old key
                                LinkedHashMap::new                      // returns a LinkedHashMap, keep order
                        ));

        System.out.println("Result 1 : " + result1);

    }
}

Output


Result 1 : {aws.amazon.com=200000, digitalocean.com=120000, linode.com=100000, liquidweb.com=80000, mkyong.com=1}

P.S In above example, the stream is sorted before collect, so the “linode.com=100000” became the ‘oldValue’.

References

  1. Java 8 Collectors JavaDoc
  2. Java 8 – How to sort a Map
  3. Java 8 Lambda : Comparator example

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
20 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
nipun
5 years ago

you should also include the scenario where duplicate key values should be added in linkedList.

guest
7 years ago

This not working:
Map result1 = list.stream().collect(
Collectors.toMap(Hosting::getId, Hosting));

shiguang.ma
6 years ago
Reply to  guest

Collectors.toMap(h -> h.getId(), h -> h)

ZeaLot4J
5 years ago
Reply to  shiguang.ma

Function.identity() is the best

Harsh Dadhich
7 years ago
Reply to  guest

Hosting::this –> try this

dsh
6 years ago
Reply to  Harsh Dadhich

dfdh

visitor
5 years ago

no matter we comment mkyong never response 😛

Prashant
6 years ago

If u have to create a map<Integer , List> this code won’t work e.g.
list.add(new Hosting(1, “liquidweb.com”, 80000));
list.add(new Hosting(1, “liquidweb1.com”, 90000));

and u want map to have 1={“liquidweb.com” ,”liquidweb1.com” }

Saurabh Kulkarni
5 years ago
Reply to  Prashant

Any solution to get Map of Key, value(as list)? I need it. as explained by Prashant

Anton
5 years ago

Multimap multimap = ArrayListMultimap.create();
list.forEach(v -> multimap.put(v.getId(), v.getId()));

Anton
5 years ago

Multimap multimap = create();
entry.getValue().forEach(v -> multimap.put(v.id(), v.getid()));

Sagar
2 years ago

Thank you for this blog, helped me a lot to understand in detail the concept.

Ammar Akouri
3 years ago

Thank you, I came for the first need/case, I ended finding all the things I needed

kevin
3 years ago

Thanks, the best examples found so far.

Matt
5 years ago

Huge help, thank you sir.

Neshi
6 years ago

Its really nice example … could You please add also an example when we want to create a multi key map from list ? I thing it could be a really helpfull.

Farhan
3 years ago

Hi Mkyoung, it should be like (newValue, oldValue). I mean second parameter represent old value not first but in your code you referring first parameter as oldValue.

Your code: //Because here it will Old value
Map result1 = list.stream().collect(
Collectors.toMap(Hosting::getName, Hosting::getWebsites,
(oldValue, newValue) -> newvalue //Because here it will Old value
)
);

But it should be for newValue
Map result1 = list.stream().collect(
Collectors.toMap(Hosting::getName, Hosting::getWebsites,
(newValue, oldValue) -> newvalue
)
);

Manishkumar Modi
6 years ago

Hi Mkyong,
My reuirement is to convert List<Map to List

Manishkumar Modi
6 years ago

Hi Mkyong,
My reuirement is to convert List<Map to List
Please share example