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