We often come up with requirements where we need to convert the list into a map. In this article, we will learn how to do it before and after Java 8. To understand this, we will be creating a Person class with attributes – id, firstName, lastName, and age.
Declaration of Person class
package com.codekru.model;
public class Person {
private int id;
private String firstName;
private String lastName;
private Integer age;
public Person() {
}
public Person(int id, String firstName, String lastName, Integer age) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// getters and setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Now we will create a list of person objects and will try to convert it into a map.
Before Java 8
If we are using java version 7 or lower, then we need to iterate over person list and put them into map.
package com.codekru.main;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.codekru.model.Person;
public class ListToMapBeforeJava8 {
public static void main(String[] args) {
// creating a list of Person
List<Person> personList = new ArrayList<>();
personList.add(new Person(1, "Will", "Smith", 48));
personList.add(new Person(2, "Roy", "Kapoor", 45));
personList.add(new Person(3, "Michael", "Clark", 53));
personList.add(new Person(4, "Ranvir", "Singh", 58));
// iterating over the list to put individual Person into personMap
Map<Integer, Person> personMap = new HashMap<>();
for (Person person : personList) {
personMap.put(person.getId(), person);
}
System.out.println(personMap.get(2).getFirstName()); // Roy
}
}
Output –
Roy
Using Java 8
In Java 8, we will be using Stream and Collectors classes to convert a List into the Map. Collectors.toMap() function can be used to fulfill that purpose.
package com.codekru.main;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.codekru.model.Person;
public class ListToMapJava8 {
public static void main(String[] args) {
// creating a list of Person
List<Person> personList = new ArrayList<>();
personList.add(new Person(1, "Will", "Smith", 48));
personList.add(new Person(2, "Roy", "Kapoor", 45));
personList.add(new Person(3, "Michael", "Clark", 53));
personList.add(new Person(4, "Ranvir", "Singh", 58));
Map<Integer, Person> personMap = personList.stream().
collect(Collectors.toMap(Person::getId, person -> person));
System.out.println(personMap.get(2).getFirstName()); // Roy
}
}
Output –
Roy
What is happening here actually? First, we converted personList into a stream, then Collections.toMap will take two arguments, keyMapper and ValueMapper ( key and value pair for the map, here we used Person Id attribute as key and Person object as value) and will return a Collector, which will further be collected by stream().collect() function and finally we will return the required map.
Note: In valueMapper, we have used person->person. In place of this, Function.identity() can also be used.
Now, what will happen if there are duplicate keys or in this case, two persons with the same id?
If there happens to be any duplicate keys that are used in Collectors.toMap method, then an IllegalStateException will be thrown as shown below
Exception in thread "main" java.lang.IllegalStateException: Duplicate key
com.codekru.model.Person@7699a589
To overcome this, we can use Collectors.toMap mergeFunction overloaded method. This function will be used for the handling of duplicate keys. So, if there happen to be any duplicate keys, then we have a choice to return any of the keys with their respective values, below we are returning person1.
package com.codekru.main;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.codekru.model.Person;
public class ListToMapJava8 {
public static void main(String[] args) {
// creating a list of Person
List<Person> personList = new ArrayList<>();
personList.add(new Person(1, "Will", "Smith", 48));
personList.add(new Person(1, "Roy", "Kapoor", 45));
personList.add(new Person(3, "Michael", "Clark", 53));
personList.add(new Person(4, "Ranvir", "Singh", 58));
Map<Integer, Person> personMap = personList.stream()
.collect(Collectors.toMap(Person::getId, person -> person, (person1, person2) -> {
return person1;
}));
System.out.println(personMap.get(1).getFirstName()); // Will
}
}
Output –
Will
As we can see, an exception is not thrown here and Will is printed. If we want to add the other object into the map, then we need to return person2 as shown below in the code.
package com.codekru.main;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.codekru.model.Person;
public class ListToMapJava8 {
public static void main(String[] args) {
List<Person> personList = new ArrayList<>();
personList.add(new Person(1, "Will", "Smith", 48));
personList.add(new Person(1, "Roy", "Kapoor", 45));
personList.add(new Person(3, "Michael", "Clark", 53));
personList.add(new Person(4, "Ranvir", "Singh", 58));
Map<Integer, Person> personMap = personList.stream()
.collect(Collectors.toMap(Person::getId, person -> person, (person1, person2) -> {
return person2;
}));
System.out.println(personMap.get(1).getFirstName()); // Roy
}
}
Output –
Roy
In this post, we have learnt how to convert list into map before java 8 and using java 8.
Hope you liked the article. If you have any doubts or concerns, please feel free to write us in comments or mail us at admin@codekru.com