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

HostingSite.java

package com.favtuts.java8;

public class HostingSite {

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

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

    //getters, setters and toString()
    @Override
    public String toString() {
        return "Hosting{" +
            " Id='" + getId() + "'" +
            ", name='" + getName() + "'" +
            ", websites='" + getWebsites() + "'" +
            "}";
    }

    public int getId() {
        return this.Id;
    }

    public void setId(int Id) {
        this.Id = Id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getWebsites() {
        return this.websites;
    }

    public void setWebsites(long websites) {
        this.websites = websites;
    }
}

1. List to Map – Collectors.toMap()

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

TestListMap.java

package com.favtuts.java8;

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

public class Java8TestListMap {

    public static void main(String[] args) {

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

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

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

        // key = name, value - websites
        Map<String, Long> result2 = list.stream().collect(
                Collectors.toMap(HostingSite::getName, HostingSite::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=tuts.heomi.net}
Result 2 : {tuts.heomi.net=1, liquidweb.com=80000, digitalocean.com=120000, linode.com=90000, aws.amazon.com=200000}
Result 3 : {1=liquidweb.com, 2=linode.com, 3=digitalocean.com, 4=aws.amazon.com, 5=tuts.heomi.net}

2. List to Map – Duplicated Key!

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

TestDuplicatedKey.java

package com.favtuts.java8;

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

public class Java8TestListMap {

    public static void main(String[] args) {
        testListToMapDuplicatedKey();
    }

    private static void testListToMapDuplicatedKey() {
        List<HostingSite> list = new ArrayList<>();
        list.add(new HostingSite(1, "liquidweb.com", 80000));
        list.add(new HostingSite(2, "linode.com", 90000));
        list.add(new HostingSite(3, "digitalocean.com", 120000));
        list.add(new HostingSite(4, "aws.amazon.com", 200000));
        list.add(new HostingSite(5, "tuts.heomi.net", 1));
		
        list.add(new HostingSite(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(HostingSite::getName, HostingSite::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(HostingSite::getName, HostingSite::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(HostingSite::getName, HostingSite::getWebsites,
                        (oldValue, newValue) -> newvalue
                )
        );

Output

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

3. List to Map – Sort & Collect

TestSortCollect.java

package com.favtuts.java8;

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

public class Java8TestListMap {

    public static void main(String[] args) {
        sortListToMap();
    }

    private static void sortListToMap() {
        List<HostingSite> list = new ArrayList<>();
        list.add(new HostingSite(1, "liquidweb.com", 80000));
        list.add(new HostingSite(2, "linode.com", 90000));
        list.add(new HostingSite(3, "digitalocean.com", 120000));
        list.add(new HostingSite(4, "aws.amazon.com", 200000));
        list.add(new HostingSite(5, "tuts.heomi.net", 1));
        list.add(new HostingSite(6, "linode.com", 100000));

        //example 1
        Map result1 = list.stream()
                .sorted(Comparator.comparingLong(HostingSite::getWebsites).reversed())
                .collect(
                        Collectors.toMap(
                            HostingSite::getName, HostingSite::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, tuts.heomi.net=1}

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

Download Source Code

$ git clone https://github.com/favtuts/java-core-tutorials-examples

$ cd java-basic/java8

References

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

Leave a Reply

Your email address will not be published. Required fields are marked *