Convert List to Map in Java

In day-to-day coding, we encounter various situations where we have to get a List from a Map to meet various requirements. In this post, learn how we can convert a given List to a Java Map.

1. Introduction

List Interface is the child interface of Collection. It is ordered, index-based and allows duplicate elements. There are various implementation classes for List Interface like ArrayList, LinkedList, etc.

Map Interface represents a group of objects as key-value pair. The keys of a Map are always unique, means duplicate keys are not allowed in a Map, but we can have duplicate values. There are various implementation classes for Map like HashMap, LinkedHashMap, TreeMap, etc.

2. Different Ways to convert List to Map

Let’s now look at the various ways by which we can convert a List into a Map.

We have an Employee record having id and name as fields. For demo, we are creating two lists,

  • ‘uniqueEmployeeList’ contains employee data having a unique id for all employees.
  • ‘duplicateEmployeeList’ contains employee data having duplicated IDs for some employees.
record Employee(int id, String name) {
}
// Creating unique employee data list
List<Employee> uniqueEmployeeList = new ArrayList<>();

// Creating duplicate employee data list
List<Employee> duplicateEmployeeList = new ArrayList<>();

//Add records to both lists

2.1. Using forEach() Loop

Let’s use the forEach() loop to iterate over the List of employees and add the corresponding key and value in a Map using put() method.

Map<Integer, Employee> employeeMap = new HashMap<>();

for(Employee employee: uniqueEmployeeList) {

  employeeMap.put(employee.id(), employee);
}

Instead of unique employees list if we use the list containing duplicate employees, then the old value will be replaced by the new value for that key in the created Map. To avoid this, we can place a ConcurrentList to store all Employee records for a given key.

Map<Integer, List> employeeMapWithListValue = new HashMap<>();

for(Employee employee: duplicateEmployeeList) {
  if(employeeMapWithListValue.containsKey(employee.id())) {
    employeeMapWithListValue.get(employee.id()).add(employee);
  } else {
    ArrayList<Employee> list = new ArrayList<>();
    list.add(employee);
    employeeMapWithListValue.put(employee.id(), list);
  }
}

2.2. Using Collectors.toMap()

Since Java version 1.8, we can have Streams and collectors to convert a List into a Map by using toMap() method.

Map<Integer, Employee> employeeMap = uniqueEmployeeList.stream()
    .collect(Collectors.toMap(Employee::id, Function.identity()));

If we use duplicate employees list then toMap() method rise IllegalStateException. To resolve this, we have to use another variant of toMap() method that takes the third argument as the merge function which is used to resolve collisions between values associated with the same key.

Map<Integer, List<Employee>> employeeMapWithListValue = duplicateEmployeeList.stream()
	.collect(Collectors.toMap(item -> item.id(),
	    item -> new ArrayList<>(Arrays.asList(item)),
	    (l1, l2) -> {
	      l1.addAll(l2);
	      return l1;
	    }));		

2.3. Using Collectors.groupingBy()

We can use groupingBy() method is best used when we have duplicate elements in the List, and we want to create a Map with unique keys and all the values associated with the duplicate key in a List i.e. if we want to maintain all the values associated with the same key in the Map then we use this method.

Map<Integer, List<Employee>> employeeMapWithListValue = duplicateEmployeeList.stream()
      .collect(Collectors.groupingBy(Employee::id,
          Collectors.mapping(Function.identity(), Collectors.toList())));

Notice the program output, all the values associated with duplicate employee-id ‘1’ and ‘2’ are maintained in a List and it returns a Map with key as Integer and value as List<Employee>.

2.4. Apache Commons Collection’s MapUtils.populateMap()

We can use MapUtils class present in Apache Commons Collections library to create a Map from a List.

Map<Integer, Employee> employeeMap = new HashMap<>();

MapUtils.populateMap(employeeMap, uniqueEmployeeList, Employee::id);

In case of duplicate values in the List, we can use the Multimap type that automatically stores multiple values in a list that are mapped to a single key.

Multimap employeeMultiMap = ArrayListMultimap.create();

duplicateEmployeeList.stream().forEach(e -> employeeMultiMap.put(e.id(), e));

2.5. Using Guava’s Maps.uniqueIndex()

We can use Maps class uniqueIndex() method of Guava library to create a Map from a List as well.

Map<Integer, Employee> employeeMap = Maps.uniqueIndex(uniqueEmployeeList, Employee::id);

Just like Collectors.toMap() method stated above, if the list contains duplicate records, then uniqueIndex() method also raises IllegalStateException.

To resolve this, we can use MultiMaps.index() method of Guava library which does the same thing but returns a Multimap (which can contain an arbitrary number of values per key) just like Collectors.groupingBy() method.

ImmutableListMultimap<Integer, Employee> employeeMap = Multimaps.index(duplicateEmployeeList, Employee::id);

3. Conclusion

We have learned the various ways by which we can convert a List into a Map in Java. We have covered both scenarios where a List contains unique elements as well as when a List contains duplicate elements.

Happy Learning !!

Sourcecode on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.