Como converter lista em mapa em Java
1. Visão geral
ConverterList emMap é uma tarefa comum. Neste tutorial, cobriremos várias maneiras de fazer isso.
Vamos supor que cada elemento deList tem um identificador que será usado como uma chave noMap resultante.
2. Estrutura de dados de amostra
Em primeiro lugar, vamos modelar o elemento:
public class Animal {
private int id;
private String name;
// constructor/getters/setters
}
O campoid é único, portanto, podemos torná-lo a chave.
Vamos começar a converter pela maneira tradicional.
3. Antes do Java 8
Evidentemente, podemos converterList emMap , sustentando os principais métodos Java:
public Map convertListBeforeJava8(List list) {
Map map = new HashMap<>();
for (Animal animal : list) {
map.put(animal.getId(), animal);
}
return map;
}
Vamos testar a conversão:
@Test
public void whenConvertBeforeJava8_thenReturnMapWithTheSameElements() {
Map map = convertListService
.convertListBeforeJava8(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
4. Com Java 8
A partir do Java 8, podemos converterList emMap usando streams eCollectors:
public Map convertListAfterJava8(List list) {
Map map = list.stream()
.collect(Collectors.toMap(Animal::getId, animal -> animal));
return map;
}
Mais uma vez, vamos garantir que a conversão seja feita corretamente:
@Test
public void whenConvertAfterJava8_thenReturnMapWithTheSameElements() {
Map map = convertListService.convertListAfterJava8(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
5. Usando a biblioteca Guava
Além do Java principal, podemos usar bibliotecas de terceiros para a conversão.
5.1. Configuração do Maven
Em primeiro lugar, precisamos adicionar a seguinte dependência ao nossopom.xml:
com.google.guava
guava
23.6.1-jre
A versão mais recente desta biblioteca pode sempre ser encontradahere.
5.2. Conversão comMaps.uniqueIndex()
Em segundo lugar, vamos usar o métodoMaps.uniqueIndex() para converter umList em umMap:
public Map convertListWithGuava(List list) {
Map map = Maps
.uniqueIndex(list, Animal::getId);
return map;
}
Finalmente, vamos testar a conversão:
@Test
public void whenConvertWithGuava_thenReturnMapWithTheSameElements() {
Map map = convertListService
.convertListWithGuava(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
6. Usando a Biblioteca Apache Commons
Também podemos fazer uma conversão com o método method da biblioteca Apache Commons.
6.1. Configuração do Maven
Em primeiro lugar, vamos incluir a dependência Maven:
org.apache.commons
commons-collections4
4.2
A versão mais recente desta dependência está disponívelhere.
6.2. MapUtils
Em segundo lugar, faremos a conversão usandoMapUtils.populateMap():
public Map convertListWithApacheCommons2(List list) {
Map map = new HashMap<>();
MapUtils.populateMap(map, list, Animal::getId);
return map;
}
Por último, vamos garantir que funcione conforme o esperado:
@Test
public void whenConvertWithApacheCommons2_thenReturnMapWithTheSameElements() {
Map map = convertListService
.convertListWithApacheCommons2(list);
assertThat(
map.values(),
containsInAnyOrder(list.toArray()));
}
7. Conflito de Valores
Vamos verificar o que acontece se o campoid não for único.
7.1. List deAnimals com duplicadoids
Em primeiro lugar, vamos criar umList deAnimals comids não exclusivo:
@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);
}
Como mostrado acima,cowegoat têm o mesmoid.
7.2. Verificando o comportamento
Java Map‘s put() method is implemented so that the latest added value overwrites the previous one with the same key.
Por esse motivo, a conversão tradicional e o Apache CommonsMapUtils.populateMap() se comportam da mesma maneira:
@Test
public void whenConvertBeforeJava8_thenReturnMapWithRewrittenElement() {
Map map = convertListService
.convertListBeforeJava8(duplicatedIdList);
assertThat(map.values(), hasSize(4));
assertThat(map.values(), hasItem(duplicatedIdList.get(4)));
}
@Test
public void whenConvertWithApacheCommons_thenReturnMapWithRewrittenElement() {
Map map = convertListService
.convertListWithApacheCommons(duplicatedIdList);
assertThat(map.values(), hasSize(4));
assertThat(map.values(), hasItem(duplicatedIdList.get(4)));
}
Como pode ser visto,goat substituicow com o mesmoid.
Ao contrário disso,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. Conclusão
Neste artigo rápido, cobrimos várias maneiras de converter exemplos deList emMap, com o núcleo do Java, bem como algumas bibliotecas populares de terceiros.
Como de costume, o código-fonte completo está disponívelover on GitHub.