java-list-to-map
How to Convert List to Map in Java
1. Overview
We’ll assume that each element of the List has an identifier which will be used as a key in the resulting Map.
2. Sample Data Structure
public class Animal {
private int id;
private String name;
// constructor/getters/setters
}
The id field is unique, hence we can make it the key.
Let’s start converting with the traditional way.
3. Before Java 8
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;
}
Let’s test the conversion:
@Test
public void whenConvertBeforeJava8_thenReturnMapWithTheSameElements() {
Map<Integer, Animal> map = convertListService
.convertListBeforeJava8(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
4. With Java 8
public Map<Integer, Animal> convertListAfterJava8(List<Animal> list) {
Map<Integer, Animal> map = list.stream()
.collect(Collectors.toMap(Animal::getId, animal -> animal));
return map;
}
Again, let’s make sure the conversion is done correctly:
@Test
public void whenConvertAfterJava8_thenReturnMapWithTheSameElements() {
Map<Integer, Animal> map = convertListService.convertListAfterJava8(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
5. Using the Guava Library
5.1. Maven Configuration
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.6.1-jre</version>
</dependency>
The latest version of this library can always be found here.
5.2. Conversion With Maps.uniqueIndex()
public Map<Integer, Animal> convertListWithGuava(List<Animal> list) {
Map<Integer, Animal> map = Maps
.uniqueIndex(list, Animal::getId);
return map;
}
Finally, let’s test the conversion:
@Test
public void whenConvertWithGuava_thenReturnMapWithTheSameElements() {
Map<Integer, Animal> map = convertListService
.convertListWithGuava(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
6. Using Apache Commons Library
6.1. Maven Configuration
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.2</version>
</dependency>
The latest version of this dependency is available here.
6.2. MapUtils
public Map<Integer, Animal> convertListWithApacheCommons2(List<Animal> list) {
Map<Integer, Animal> map = new HashMap<>();
MapUtils.populateMap(map, list, Animal::getId);
return map;
}
Lastly, let’s make sure it works as expected:
@Test
public void whenConvertWithApacheCommons2_thenReturnMapWithTheSameElements() {
Map<Integer, Animal> map = convertListService
.convertListWithApacheCommons2(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
7. Conflict of Values
7.1. List of Animals With Duplicated 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 whenConvertBeforeJava8_thenReturnMapWithRewrittenElement() {
Map<Integer, Animal> map = convertListService
.convertListBeforeJava8(duplicatedIdList);
assertThat(map.values(), hasSize(4));
assertThat(map.values(), hasItem(duplicatedIdList.get(4)));
}
@Test
public void whenConvertWithApacheCommons_thenReturnMapWithRewrittenElement() {
Map<Integer, Animal> map = convertListService
.convertListWithApacheCommons(duplicatedIdList);
assertThat(map.values(), hasSize(4));
assertThat(map.values(), hasItem(duplicatedIdList.get(4)));
}
As can be seen, the goat overwrites the cow with the same id.
Unlike that, 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’ve 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.