1. Overview
Converting List to Map is a common task. In this tutorial, we’ll cover several ways to do this.
We’ll assume that each element of the List has an identifier that will be used as a key in the resulting Map.
2. Sample Data Structure
First, we’ll model the element:
public class Animal {
private int id;
private String name;
// constructor/getters/setters
}
The id field is unique, so we can make it the key.
Let’s start converting with the traditional way.
3. Before Java 8
Evidently, we can convert a List to a Map using core Java methods:
public Map<Integer, Animal> convertListBeforeJava8(List<Animal> list) {
Map<Integer, Animal> map = new HashMap<>();
for (Animal animal : list) {
map.put(animal.getId(), animal);
}
return map;
}
Now we test the conversion:
@Test
public void givenAList_whenConvertBeforeJava8_thenReturnMapWithTheSameElements() {
Map<Integer, Animal> map = convertListService
.convertListBeforeJava8(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
4. With Java 8
Starting with Java 8, we can convert a List into a Map using streams and Collectors:
public Map<Integer, Animal> convertListAfterJava8(List<Animal> list) {
Map<Integer, Animal> map = list.stream()
.collect(Collectors.toMap(Animal::getId, Function.identity()));
return map;
}
Again, let’s make sure the conversion is done correctly:
@Test
public void givenAList_whenConvertAfterJava8_thenReturnMapWithTheSameElements() {
Map<Integer, Animal> map = convertListService.convertListAfterJava8(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
5. Using the Guava Library
Besides core Java, we can use third-party libraries for the conversion.
5.1. Maven Configuration
First, we need to add the following dependency to our pom.xml:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.2-jre</version>
</dependency>
The latest version of this library can always be found here.
5.2. Conversion With Maps.uniqueIndex()
Second, let’s use Maps.uniqueIndex() method to convert a List into a Map:
public Map<Integer, Animal> convertListWithGuava(List<Animal> list) {
Map<Integer, Animal> map = Maps
.uniqueIndex(list, Animal::getId);
return map;
}
Finally, we test the conversion:
@Test
public void givenAList_whenConvertWithGuava_thenReturnMapWithTheSameElements() {
Map<Integer, Animal> map = convertListService
.convertListWithGuava(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
6. Using Apache Commons Library
We can also make a conversion with the Apache Commons library method.
6.1. Maven Configuration
First, let’s include Maven dependency:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
The latest version of this dependency is available here.
6.2. MapUtils
Second, we’ll make the conversion using MapUtils.populateMap():
public Map<Integer, Animal> convertListWithApacheCommons(List<Animal> list) {
Map<Integer, Animal> map = new HashMap<>();
MapUtils.populateMap(map, list, Animal::getId);
return map;
}
Finally, we can make sure it works as expected:
@Test
public void givenAList_whenConvertWithApacheCommons_thenReturnMapWithTheSameElements() {
Map<Integer, Animal> map = convertListService
.convertListWithApacheCommons(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
7. Conflict of Values
Let’s check what happens if the id field isn’t unique.
*7.1. List of Animals With Duplicated Ids*
First, we create a List of Animals with non-unique ids:
@Before
public void init() {
this.duplicatedIdList = new ArrayList<>();
Animal cat = new Animal(1, "Cat");
duplicatedIdList.add(cat);
Animal dog = new Animal(2, "Dog");
duplicatedIdList.add(dog);
Animal pig = new Animal(3, "Pig");
duplicatedIdList.add(pig);
Animal cow = new Animal(4, "Cow");
duplicatedIdList.add(cow);
Animal goat= new Animal(4, "Goat");
duplicatedIdList.add(goat);
}
As shown above, the cow and the goat have the same id.
7.2. Checking the Behavior
*Java Map‘s put() method is implemented so that the latest added value overwrites the previous one with the same key.*
For this reason, the traditional conversion and Apache Commons MapUtils.populateMap() behave in the same way:
@Test
public void givenADupIdList_whenConvertBeforeJava8_thenReturnMapWithRewrittenElement() {
Map<Integer, Animal> map = convertListService
.convertListBeforeJava8(duplicatedIdList);
assertThat(map.values(), hasSize(4));
assertThat(map.values(), hasItem(duplicatedIdList.get(4)));
}
@Test
public void givenADupIdList_whenConvertWithApacheCommons_thenReturnMapWithRewrittenElement() {
Map<Integer, Animal> map = convertListService
.convertListWithApacheCommons(duplicatedIdList);
assertThat(map.values(), hasSize(4));
assertThat(map.values(), hasItem(duplicatedIdList.get(4)));
}
We can see that the goat overwrites the cow with the same id.
However, Collectors.toMap() and MapUtils.populateMap() throw IllegalStateException and IllegalArgumentException respectively:
@Test(expected = IllegalStateException.class)
public void givenADupIdList_whenConvertAfterJava8_thenException() {
convertListService.convertListAfterJava8(duplicatedIdList);
}
@Test(expected = IllegalArgumentException.class)
public void givenADupIdList_whenConvertWithGuava_thenException() {
convertListService.convertListWithGuava(duplicatedIdList);
}
8. Conclusion
In this quick article, we covered various ways of converting a List to a Map, giving examples with core Java as well as some popular third-party libraries.
As usual, the complete source code is available over on GitHub.