Conversion of List to Map in Java 8

In this article, we will discuss how to convert List into Map in Java 8

Already, in the last article we have discussed how to convert List to Map prior to Java 8 version

 

Again, we will recap few things before proceedings with code examples using Java 8 Streams

List v/s Map:

Before starting with List to Map conversion, we should understand difference between List and Map

  • List stores group of objects as single unit/entity where it allows duplicates objects maintaining insertion order
  • Map stores group of key-value pairs as single unit/entity where keys must be unique and values can be duplicated

So, we need to decide what we want to put inside Map as key and value. Ideally, whenever list stores group of some objects having 2 or more attributes then we can simply choose any 2-attributes for key and value while putting inside Map.

 

We will cover below examples for Java 8 List to Map conversion,

  1. Id can be chosen as key and any other attribute like name can selected for value
  2. Again Id can be chosen as key and whole object as value
  3. What happens, if there are duplicate keys while converting List to Map
  4. Solution for duplicate keys, if duplicate objects present in List
  5. How to preserve insertion order of the List while converting List to Map using LinkedHashMap
  6. While converting List to Map, store keys inside Map according to natural sorting order of keys using TreeMap

 

Let’s move forward and implement above listed examples,

Employee POJO:

Employee with 4-attributes namely

  • Id
  • name
  • age
  • designation

Employee.java

package in.bench.resources.java8.list.to.map;

public class Employee {

	// member variables
	private int empId;
	private String empName;
	private int empAge;
	private String empDesignation;

	// 4-arg parameterized constructor
	public Employee(int empId, String empName, int empAge, String empDesignation) {
		super();
		this.empId = empId;
		this.empName = empName;
		this.empAge = empAge;
		this.empDesignation = empDesignation;
	}

	// getter & setter
	public int getEmpId() {
		return empId;
	}
	public void setEmpId(int empId) {
		this.empId = empId;
	}
	public String getEmpName() {
		return empName;
	}
	public void setEmpName(String empName) {
		this.empName = empName;
	}
	public int getEmpAge() {
		return empAge;
	}
	public void setEmpAge(int empAge) {
		this.empAge = empAge;
	}
	public String getEmpDesignation() {
		return empDesignation;
	}
	public void setEmpDesignation(String empDesignation) {
		this.empDesignation = empDesignation;
	}

	// override toString()
	@Override
	public String toString() {
		return "Employee [empId=" + empId + ", empName=" + empName
				+ ", empAge=" + empAge + ", empDesignation=" + empDesignation
				+ "]";
	}
}

 

1. Convert List to Map with 2-attributes of POJO as Key-Value pair

Here,

  • Id is selected as key
  • Name for value
  • refer above Employee POJO for attribute details

ConvertListToMap.java

package in.bench.resources.java8.list.to.map;

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

public class ConvertListToMapInJava8 {

	public static void main(String[] args) {

		// create ArrayList
		List<Employee> employees = new ArrayList<Employee>();

		// add employee objects to list
		employees.add(new Employee(1001, "SJ", 18, "Consultant"));
		employees.add(new Employee(1002, "AK", 20, "Enginner"));
		employees.add(new Employee(1003, "PJ", 23, "Developer"));

		// printing to console - List of Employees
		System.out.println("List of Employee : \n");

		// print to console using Java 8 for-each
		employees.forEach((employee) -> System.out.println(employee));

		// convert List<Employee> to Map<empId, empName> using Java 8 Streams
		Map<Integer, String> mapOfEmployees = employees.stream().collect(
				Collectors.toMap(
						e -> e.getEmpId(), 
						e -> e.getEmpName()));

		// printing to console - Map of Employees
		System.out.println("\n\nMap of Employee : \n");

		// print to console using Java 8 for-each
		mapOfEmployees.forEach(
				(key, value) -> System.out.println("Key: " + key +"\tValue: "+ value));
	}
}

Output:

List of Employee : 

Employee [empId=1001, empName=SJ, empAge=18, empDesignation=Consultant]
Employee [empId=1002, empName=AK, empAge=20, empDesignation=Enginner]
Employee [empId=1003, empName=PJ, empAge=23, empDesignation=Developer]


Map of Employee : 

Key: 1001	Value: SJ
Key: 1002	Value: AK
Key: 1003	Value: PJ

 

2. Convert List to Map with primary Id as Key and complete object as value

Again,

  • Id is selected as key
  • whole object for value
  • refer above Employee POJO for attribute details

ConvertListToMapOfEmployee.java

package in.bench.resources.java8.list.to.map;

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

public class ConvertListToMapOfEmployeeInJava8 {

	public static void main(String[] args) {

		// create ArrayList
		List<Employee> employees = new ArrayList<Employee>();

		// add employee objects to list
		employees.add(new Employee(1001, "SJ", 18, "Consultant"));
		employees.add(new Employee(1002, "AK", 20, "Enginner"));
		employees.add(new Employee(1003, "PJ", 23, "Developer"));

		// printing to console - List of Employee
		System.out.println("List of Employee : \n");

		// print to console using Java 8 for-each
		employees.forEach((employee) -> System.out.println(employee));

		// convert List<Employee> to Map<empId, empName> using Java 8 Streams
		Map<Integer, Employee> mapOfEmployees = employees.stream().collect(
				Collectors.toMap(
						e -> e.getEmpId(), 
						e -> e));

		// printing to console - Map of Employee
		System.out.println("\n\nMap of Employee : \n");

		// print to console using Java 8 for-each
		mapOfEmployees.forEach(
				(key, value) -> System.out.println("Key: " + key +"\tValue: "+ value));
	}
}

Output:

List of Employee : 

Employee [empId=1001, empName=SJ, empAge=18, empDesignation=Consultant]
Employee [empId=1002, empName=AK, empAge=20, empDesignation=Enginner]
Employee [empId=1003, empName=PJ, empAge=23, empDesignation=Developer]


Map of Employee : 

Key: 1001	Value: Employee [empId=1001, empName=SJ, empAge=18, empDesignation=Consultant]
Key: 1002	Value: Employee [empId=1002, empName=AK, empAge=20, empDesignation=Enginner]
Key: 1003	Value: Employee [empId=1003, empName=PJ, empAge=23, empDesignation=Developer]

 

3. Convert List to Map – with duplicate keys

  • While converting List to Map, we are choosing employee Id as key for Map and in the list objects there are 2 objects with same employee Id
  • This results in throwing IllegalStateException for duplicate keys, as shown in the output console
  • Note: Ideally, there shouldn’t be 2 employees with same Id. But here we kept same Id for 2 employees for demo purpose
  • In the following example, we will fix this issue using Merge function similar to group-by clause

ConvertListToMapWithDuplicateKeysInJava8.java

package in.bench.resources.java8.list.to.map;

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

public class ConvertListToMapWithDuplicateKeysInJava8 {

	public static void main(String[] args) {

		// create ArrayList
		List<Employee> employees = new ArrayList<Employee>();

		// add employee objects to list
		employees.add(new Employee(1001, "SJ", 18, "Consultant"));
		employees.add(new Employee(1002, "AK", 20, "Enginner"));
		employees.add(new Employee(1003, "PJ", 23, "Developer"));
		employees.add(new Employee(1003, "SK", 25, "Manager")); // duplicate record

		// printing to console - List of Employees
		System.out.println("List of Employee : \n");

		// print to console using Java 8 for-each
		employees.forEach((employee) -> System.out.println(employee));

		// convert List<Employee> to Map<empId, empName> using Java 8 Streams
		Map<Integer, String> mapOfEmployees = employees.stream().collect(
				Collectors.toMap(
						e -> e.getEmpId(), 
						e -> e.getEmpName()));

		// printing to console - Map of Employees
		System.out.println("\n\nMap of Employee : \n");

		// print to console using Java 8 for-each
		mapOfEmployees.forEach(
				(key, value) -> System.out.println("Key: " + key +"\tValue: "+ value));
	}
}

Output:

List of Employee : 

Employee [empId=1001, empName=SJ, empAge=18, empDesignation=Consultant]
Employee [empId=1002, empName=AK, empAge=20, empDesignation=Enginner]
Employee [empId=1003, empName=PJ, empAge=23, empDesignation=Developer]
Employee [empId=1003, empName=SK, empAge=25, empDesignation=Manager]
Exception in thread "main" java.lang.IllegalStateException: Duplicate key PJ
	at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
	at java.util.HashMap.merge(HashMap.java:1245)
	at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
	at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
	at in.bench.resources.java8.list.to.map.ConvertListToMapWithDuplicateKeysInJava8
.main(ConvertListToMapWithDuplicateKeysInJava8.java:29)

 

4. Convert List to Map – solution for duplicate keys

  • While converting List to Map, if there are duplicate keys present then it throws IllegalStateException
  • Solution: To overcome IllegalStateException for duplicate keys, we can simply add 3rd parameter in the Collectors.toMap(); method which takes BinaryOperator
  • This is also called as Merge function
  • You will understand, once going through below example as it works very similar to group-by clause

ConvertListToMapSolutionForDuplicateKeysInJava8.java

package in.bench.resources.java8.list.to.map;

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

public class ConvertListToMapSolutionForDuplicateKeysInJava8 {

	public static void main(String[] args) {

		// create ArrayList
		List<Employee> employees = new ArrayList<Employee>();

		// add employee objects to list
		employees.add(new Employee(1001, "SJ", 18, "Consultant"));
		employees.add(new Employee(1002, "AK", 20, "Enginner"));
		employees.add(new Employee(1003, "PJ", 23, "Developer"));
		employees.add(new Employee(1003, "SK", 25, "Manager"));

		// printing to console - List of Employees
		System.out.println("List of Employee : \n");

		// print to console using Java 8 for-each
		employees.forEach((employee) -> System.out.println(employee));

		// convert List<Employee> to Map<empId, empName> using Java 8 Streams
		Map<Integer, String> mapOfEmployees = employees.stream().collect(
				Collectors.toMap(
						e -> e.getEmpId(), 
						e -> e.getEmpName(), 
						(e1, e2) -> e1 + ", " + e2)); // Merge Function

		// printing to console - Map of Employees
		System.out.println("\n\nMap of Employee : \n");

		// print to console using Java 8 for-each
		mapOfEmployees.forEach(
				(key, value) -> System.out.println("Key: " + key +"\tValue: "+ value));
	}
}

Output:

List of Employee : 

Employee [empId=1001, empName=SJ, empAge=18, empDesignation=Consultant]
Employee [empId=1002, empName=AK, empAge=20, empDesignation=Enginner]
Employee [empId=1003, empName=PJ, empAge=23, empDesignation=Developer]
Employee [empId=1003, empName=SK, empAge=25, empDesignation=Manager]


Map of Employee : 

Key: 1001	Value: SJ
Key: 1002	Value: AK
Key: 1003	Value: PJ, SK

 

5. Convert List to Map – preserving order of List while converting using LinkedHashMap

  • While converting List to Map, we can certainly convert using Java 8 Stream but it doesn’t guarantees insertion order similar to that of List objects
  • To achieve this, we can pass 4th parameter to Collectors.toMap(); method which takes what type of result needs to be returned
  • This is also called as Map Supplier
  • You will understand, once going through below example
  • This is basically tells where results needs to be stored after List to Map conversion
  • In all earlier examples, when nothing is passed then by default results stored in HashMap
  • whereas when we define LinkedHashMap then results stored inside LHM which guarantees insertion order (similar to that of List objects, as per iteration)
  • Similarly, if we take TreeMap then it will be sorted while converting List to Map

ConvertListToMapOfEmployeePreservingOrderInJava8.java

package in.bench.resources.java8.list.to.map;

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

public class ConvertListToMapOfEmployeePreservingOrderInJava8 {

	public static void main(String[] args) {

		// create ArrayList
		List<Employee> employees = new ArrayList<Employee>();

		// add employee objects to list
		employees.add(new Employee(1001, "SJ", 18, "Consultant"));
		employees.add(new Employee(1002, "AK", 20, "Enginner"));
		employees.add(new Employee(1003, "PJ", 23, "Developer"));

		// printing to console - List of Employee
		System.out.println("List of Employee : \n");

		// print to console using Java 8 for-each
		employees.forEach((employee) -> System.out.println(employee));

		// convert List<Employee> to Map<empId, empName> using Java 8 Streams
		Map<Integer, String> mapOfEmployees = employees.stream().collect(
				Collectors.toMap(
						e -> e.getEmpId(), 
						e -> e.getEmpName(), 
						(e1, e2) -> e1 + ", " + e2, // Merge Function
						LinkedHashMap<Integer, String>::new)); // Map Supplier

		// printing to console - Map of Employee
		System.out.println("\n\nMap of Employee preserving Insertion order : \n");

		// print to console using Java 8 for-each
		mapOfEmployees.forEach(
				(key, value) -> System.out.println("Key: " + key +"\tValue: "+ value));
	}
}

Output:

List of Employee : 

Employee [empId=1001, empName=SJ, empAge=18, empDesignation=Consultant]
Employee [empId=1002, empName=AK, empAge=20, empDesignation=Enginner]
Employee [empId=1003, empName=PJ, empAge=23, empDesignation=Developer]


Map of Employee preserving Insertion order : 

Key: 1001	Value: SJ
Key: 1002	Value: AK
Key: 1003	Value: PJ

 

6. Convert List to Map – natural sorting order of keys using TreeMap

  • While converting List to Map, we can also sort keys using TreeMap
  • This example is very similar to above example with only difference is that earlier example preserves insertion order whereas this example sorts keys in natural order

ConvertListToMapOfEmployeeSortingOrderInJava8.java

package in.bench.resources.java8.list.to.map;

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

public class ConvertListToMapOfEmployeeSortingOrderInJava8 {

	public static void main(String[] args) {

		// create ArrayList
		List<Employee> employees = new ArrayList<Employee>();

		// add employee objects to list
		employees.add(new Employee(1009, "SJ", 18, "Consultant"));
		employees.add(new Employee(1003, "AK", 20, "Enginner"));
		employees.add(new Employee(1007, "PJ", 23, "Developer"));

		// printing to console - List of Employee
		System.out.println("List of Employee : \n");

		// print to console using Java 8 for-each
		employees.forEach((employee) -> System.out.println(employee));

		// convert List<Employee> to Map<empId, empName> using Java 8 Streams
		Map<Integer, String> mapOfEmployees = employees.stream().collect(
				Collectors.toMap(
						e -> e.getEmpId(), 
						e -> e.getEmpName(), 
						(e1, e2) -> e1 + ", " + e2, // Merge Function
						TreeMap<Integer, String>::new)); // Map Supplier

		// printing to console - Map of Employee
		System.out.println("\n\nMap of Employee sorted acc. to natural order of keys : \n");

		// print to console using Java 8 for-each
		mapOfEmployees.forEach(
				(key, value) -> System.out.println("Key: " + key +"\tValue: "+ value));
	}
}

Output:

List of Employee : 

Employee [empId=1009, empName=SJ, empAge=18, empDesignation=Consultant]
Employee [empId=1003, empName=AK, empAge=20, empDesignation=Enginner]
Employee [empId=1007, empName=PJ, empAge=23, empDesignation=Developer]


Map of Employee sorted according to natural order of keys : 

Key: 1003	Value: AK
Key: 1007	Value: PJ
Key: 1009	Value: SJ

 

Hope, you found this article very helpful. If you any suggestion or want to contribute any other way or tricky situation you faced during Interview hours, then share with us. We will include that code here.

 

References:

https://docs.oracle.com/javase/tutorial/collections/intro/
https://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html
https://docs.oracle.com/javase/7/docs/api/java/util/Collection.html
https://docs.oracle.com/javase/tutorial/collections/interfaces/list.html
https://docs.oracle.com/javase/tutorial/collections/implementations/list.html
https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html
https://docs.oracle.com/javase/7/docs/api/java/util/Map.html
https://docs.oracle.com/javase/7/docs/api/java/util/Map.Entry.html
https://docs.oracle.com/javase/tutorial/collections/interfaces/map.html
https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html

 

Read Also:

 

Happy Coding !!
Happy Learning !!

Java: String join() method
Conversion of List to Map in Java