Comment convertir une liste en carte en Java

Comment convertir une liste en carte en Java

1. Vue d'ensemble

La conversion deList enMap est une tâche courante. Dans ce didacticiel, nous aborderons plusieurs façons de procéder.

Nous supposerons que chaque élément desList a un identifiant qui sera utilisé comme clé dans lesMap résultants.

2. Exemple de structure de données

Tout d'abord, modélisons l'élément:

public class Animal {
    private int id;
    private String name;

    //  constructor/getters/setters
}

Le champid est unique, nous pouvons donc en faire la clé.

Commençons la conversion avec la méthode traditionnelle.

3. Avant Java 8

Évidemment, nous pouvons convertir unList en unMap en utilisant les méthodes Java principales:

public Map convertListBeforeJava8(List list) {
    Map map = new HashMap<>();
    for (Animal animal : list) {
        map.put(animal.getId(), animal);
    }
    return map;
}

Testons la conversion:

@Test
public void whenConvertBeforeJava8_thenReturnMapWithTheSameElements() {
    Map map = convertListService
      .convertListBeforeJava8(list);

    assertThat(
      map.values(),
      containsInAnyOrder(list.toArray()));
}

4. Avec Java 8

À partir de Java 8, nous pouvons convertir unList en unMap en utilisant des flux et desCollectors:

 public Map convertListAfterJava8(List list) {
    Map map = list.stream()
      .collect(Collectors.toMap(Animal::getId, animal -> animal));
    return map;
}

Encore une fois, vérifions que la conversion est effectuée correctement:

@Test
public void whenConvertAfterJava8_thenReturnMapWithTheSameElements() {
    Map map = convertListService.convertListAfterJava8(list);

    assertThat(
      map.values(),
      containsInAnyOrder(list.toArray()));
}

5. Utilisation de la bibliothèque Guava

Outre le noyau Java, nous pouvons utiliser des bibliothèques tierces pour la conversion.

5.1. Configuration Maven

Tout d'abord, nous devons ajouter la dépendance suivante à nospom.xml:


    com.google.guava
    guava
    23.6.1-jre

La dernière version de cette bibliothèque peut toujours être trouvéehere.

5.2. Conversion avecMaps.uniqueIndex()

Deuxièmement, utilisons la méthodeMaps.uniqueIndex() pour convertir unList en unMap:

public Map convertListWithGuava(List list) {
    Map map = Maps
      .uniqueIndex(list, Animal::getId);
    return map;
}

Enfin, testons la conversion:

@Test
public void whenConvertWithGuava_thenReturnMapWithTheSameElements() {
    Map map = convertListService
      .convertListWithGuava(list);

    assertThat(
      map.values(),
      containsInAnyOrder(list.toArray()));
}

6. Utilisation de la bibliothèque Apache Commons

Nous pouvons également effectuer une conversion avec la méthode de la bibliothèque Apache Commons.

6.1. Configuration Maven

Tout d'abord, incluons la dépendance Maven:


    org.apache.commons
    commons-collections4
    4.2

La dernière version de cette dépendance est disponiblehere.

6.2. MapUtils

Deuxièmement, nous allons effectuer la conversion en utilisantMapUtils.populateMap():

public Map convertListWithApacheCommons2(List list) {
    Map map = new HashMap<>();
    MapUtils.populateMap(map, list, Animal::getId);
    return map;
}

Enfin, assurons-nous que cela fonctionne comme prévu:

@Test
public void whenConvertWithApacheCommons2_thenReturnMapWithTheSameElements() {
    Map map = convertListService
      .convertListWithApacheCommons2(list);

    assertThat(
      map.values(),
      containsInAnyOrder(list.toArray()));
}

7. Conflit de valeurs

Voyons ce qui se passe si le champid n’est pas unique.

7.1. List deAnimals avecid en double

Tout d'abord, créons unList deAnimals avec desid non uniques:

@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);
}

Comme indiqué ci-dessus, lescow et lesgoat ont les mêmesid.

7.2. Vérification du comportement

Java Map‘s put() method is implemented so that the latest added value overwrites the previous one with the same key.

Pour cette raison, la conversion traditionnelle et Apache CommonsMapUtils.populateMap() se comportent de la même manière:

@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)));
}

Comme on peut le voir, legoat écrase lescow avec les mêmesid.

Contrairement à cela,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

Dans cet article rapide, nous avons abordé différentes manières de convertir des exemples deList enMap, giving avec le noyau Java ainsi que certaines bibliothèques tierces populaires.

Comme d'habitude, le code source complet est disponibleover on GitHub.