Core Java

Java 8 Convert a List to Map Example

Hello readers, in this tutorial, we will learn how to convert a List<?> to a Map<K,V> using Java8 Streams API.

1. Introduction

The most common task in Java programming is to convert a List of the object e.g. List<?> into a Map e.g. Map<K,V> where K is some property of the object and V is the real object. For e.g., suppose developers have a List<Person> and they want to convert it into a Map e.g., Map<PersonId, Person>, how do developers achieve that? The simplest way to do this is iterating over the List and add each element to the Map by extracting the keys and using the real element as an object. This is exactly how developers do it in the ancient Java world but JDK 1.8 has made it even simpler. In Java8, developers can get the stream from the List and then collect all the elements into a Map by using a Collector. The collect() method of the Stream class and java.util.stream.Collectors class gives developers adequate choices to decide which property goes into the key and which object goes into the value.

 
Depending upon the scenario, developers convert an ArrayList to HashMap or LinkedHashMap. Usually, when developers convert a List to a Map, they have to keep in mind some abnormalities which come from the fact that List and Map are different data structures with distinct properties. For e.g.,

  • List is an ordered collection which allows the duplicates objects while maintaining the insertion order
  • Map stores the group of key-value pairs as a single entity where keys must be unique and values can be duplicated

As Map doesn’t offer any ordering guarantee and it doesn’t allow the duplicate keys, they may lose the original order of the objects in the List. If developers care for the order they can opt for a Map implementation which provides the ordering guarantee. For e.g.,

  • LinkedHashMap which guarantee the insertion order (i.e. the order in which values are added to the map)
  • TreeMap sort the objects in their natural sorting order or the order imposed by the provided Comparator

It may be possible that the List developers are converting into a Map may contain some duplicates, which may not be a problem because when developers insert an existing key into the Map, it overrides the old value.

But, it does constitute a problem if developers try to collect the duplicate elements from Stream into a Map, without telling the Collector how to resolve the match. In short, developers may get “Exception in thread "main" java.lang.IllegalStateException: Duplicate key” exception while converting a List with duplicate elements into a Map in Java.

Developers can solve this problem by informing the Collector interface about how to handle the duplicates. The toMap() method which developers will use to convert a List to Map is overloaded and it allows developers to specify which elements to keep and which element to throw away. Now, open up the Eclipse Ide and I will explain further about converting a List of data into an equivalent Map.

2. Java8 Convert a List to Map Example

2.1 Tools Used

We are using Eclipse Oxygen, JDK 1.8 and Maven.

2.2 Project Structure

Firstly, let’s review the final project structure, in case you are confused about where you should create the corresponding files or folder later!

Fig. 1: Application Project Structure
Fig. 1: Application Project Structure

2.3 Project Creation

This section will demonstrate on how to create a Java-based Maven project with Eclipse. In Eclipse IDE, go to File -> New -> Maven Project.

Fig. 2: Create Maven Project
Fig. 2: Create Maven Project

In the New Maven Project window, it will ask you to select project location. By default, ‘Use default workspace location’ will be selected. Select the ‘Create a simple project (skip archetype selection)’ checkbox and just click on next button to proceed.

Fig. 3: Project Details
Fig. 3: Project Details

It will ask you to ‘Enter the group and the artifact id for the project’. We will input the details as shown in the below image. The version number will be by default: 0.0.1-SNAPSHOT.

Fig. 4: Archetype Parameters
Fig. 4: Archetype Parameters

Click on Finish and the creation of a maven project is completed. If you observe, it has downloaded the maven dependencies and a pom.xml file will be created. It will have the following code:

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>Java8List2Map </groupId>
	<artifactId>Java8List2Map </artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
</project>

Developers can start adding the dependencies that they want. Let’s start building the application!

3. Application Building

Below are the steps involved in developing this application.

3.1 Java Class Implementation

Let’s create the required Java files. Right-click on the src/main/java folder, New -> Package.

Fig. 5: Java Package Creation
Fig. 5: Java Package Creation

A new pop window will open where we will enter the package name as: com.jcg.java.

Fig. 6: Java Package Name (com.jcg.java)
Fig. 6: Java Package Name (com.jcg.java)

Once the package is created in the application, we will need to create the implementation class to demonstrate the List to Map conversion. Right-click on the newly created package: New -> Class.

Fig. 7: Java Class Creation
Fig. 7: Java Class Creation

A new pop window will open and enter the file name as: List2MapDemo. The implementation class will be created inside the package: com.jcg.java.

Fig. 8: Java Class (List2MapDemo.java)
Fig. 8: Java Class (List2MapDemo.java)

Here is the complete Java program using the Lambda Expression and Streams to demonstrate the use the Collectors.toMap() method in the Java8 programming.

Java8Array2List.java

package com.jcg.java;

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

public class List2MapDemo {

	public static void main(String[] args) {

		List <Person> people = new ArrayList <Person> ();
		people.add(new Person(1, "Mario", 27));
		people.add(new Person(2, "Luigi", 30));
		people.add(new Person(3, "Steve", 20));

		// Converting List to Map in Java8 Using Lambda Expression
		Map<Integer, Person> mapLambdaExpr = people.stream().collect(Collectors.toMap(p -> p.getPersonId(), p -> p));
		System.out.println("<------------Iterating Map By Lambda Expression-------------->");
		System.out.println(mapLambdaExpr);

		System.out.println();

		// Converting List to Map in Java8 Using Method Reference
		Map<Integer, Person> mapMethodRef = people.stream().collect(Collectors.toMap(Person::getPersonId, Function.identity()));
		System.out.println("<------------Iterating Map By Method Reference--------------->");
		System.out.println(mapMethodRef);

		System.out.println();

		// Duplicate Key Exception
		people.add(new Person(3, "Dave", 25));		
		Map<Integer, Person> dupMap = people.stream().collect(Collectors.toMap(p -> p.getPersonId(), p -> p));
		System.out.println("<------------Duplicate Key Exception--------------->");
		System.out.println(dupMap);
	}
}

4. Run the Application

To run the application, developers need to right-click on the class, Run As -> Java Application. Developers can debug the example and see what happens after every step!

Fig. 9: Run Application
Fig. 9: Run Application

5. Project Demo

The code shows the following logs as output.

# Logs for 'List2MapDemo' #
===========================
<------------Iterating Map By Lambda Expression-------------->
{1=[Id= 1, Name= Mario, Age= 27], 2=[Id= 2, Name= Luigi, Age= 30], 3=[Id= 3, Name= Steve, Age= 20]}

<------------Iterating Map By Method Reference--------------->
{1=[Id= 1, Name= Mario, Age= 27], 2=[Id= 2, Name= Luigi, Age= 30], 3=[Id= 3, Name= Steve, Age= 20]}

Exception in thread "main" java.lang.IllegalStateException: Duplicate key [Id= 3, Name= Steve, Age= 20]
	at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
	at java.util.HashMap.merge(HashMap.java:1253)
	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 com.jcg.java.List2MapDemo.main(List2MapDemo.java:34)

That’s all for this post. Happy Learning!

6. Conclusion

In this tutorial, we had an in-depth look at the 2 different ways of converting a given List of data into an equivalent Map. I hope this article served you whatever you were looking for.

7. Download the Eclipse Project

This was an example of List to Map conversion in Java8.

Download
You can download the full source code of this example here: Java8List2Map

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button