Apache Commons Collections MapUtils

Apache Commons Collections MapUtils

1. introduction

MapUtils est l'un des outils disponibles dans le projet Apache Commons Collections.

En termes simples, il fournit des méthodes utilitaires et des décorateurs pour travailler avec les instancesjava.util.Map etjava.util.SortedMap.

2. Installer

Commençons par ajouterthe dependency:


    org.apache.commons
    commons-collections4
    4.1

3. Méthodes utilitaires

3.1. Création d'unMap à partir d'unArray

Maintenant, configurons les tableaux que nous utiliserons pour créer une carte:

public class MapUtilsTest {
    private String[][] color2DArray = new String[][] {
        {"RED", "#FF0000"},
        {"GREEN", "#00FF00"},
        {"BLUE", "#0000FF"}
    };
    private String[] color1DArray = new String[] {
        "RED", "#FF0000",
        "GREEN", "#00FF00",
        "BLUE", "#0000FF"
    };
    private Map colorMap;

    //...
}

Voyons comment nous pouvons créer une carte à partir d'un tableau à deux dimensions:

@Test
public void whenCreateMapFrom2DArray_theMapIsCreated() {
    this.colorMap = MapUtils.putAll(
      new HashMap<>(), this.color2DArray);

    assertThat(
      this.colorMap,
      is(aMapWithSize(this.color2DArray.length)));

    assertThat(this.colorMap, hasEntry("RED", "#FF0000"));
    assertThat(this.colorMap, hasEntry("GREEN", "#00FF00"));
    assertThat(this.colorMap, hasEntry("BLUE", "#0000FF"));
}

Nous pourrions également utiliser un tableau unidimensionnel. Dans ce cas, le tableau est traité comme des clés et des valeurs dans d'autres index:

@Test
public void whenCreateMapFrom1DArray_theMapIsCreated() {
    this.colorMap = MapUtils.putAll(
      new HashMap<>(), this.color1DArray);

    assertThat(
      this.colorMap,
      is(aMapWithSize(this.color1DArray.length / 2)));

    assertThat(this.colorMap, hasEntry("RED", "#FF0000"));
    assertThat(this.colorMap, hasEntry("GREEN", "#00FF00"));
    assertThat(this.colorMap, hasEntry("BLUE", "#0000FF"));
}

3.2. Impression du contenu d'unMap

Plusieurs fois, lors du débogage ou dans les journaux de débogage, nous aimerions imprimer la totalité de la carte:

@Test
public void whenVerbosePrintMap_thenMustPrintFormattedMap() {
    MapUtils.verbosePrint(System.out, "Optional Label", this.colorMap);
}

Et le résultat:

Optional Label =
{
    RED = #FF0000
    BLUE = #0000FF
    GREEN = #00FF00
}

Nous pouvons également utiliserdebugPrint() qui imprime en plus les types de données des valeurs.

3.3. Obtenir des valeurs

MapUtils fournit des méthodes pour extraire la valeur d'une carte pour une clé donnée d'une manière sûrenull.

Par exemple,getString() obtient unString desMap. La valeurString est obtenue viatoString(). Nous pouvons éventuellement spécifier la valeur par défaut à renvoyer si la valeur estnull ou si la conversion échoue:

@Test
public void whenGetKeyNotPresent_thenMustReturnDefaultValue() {
    String defaultColorStr = "COLOR_NOT_FOUND";
    String color = MapUtils
      .getString(this.colorMap, "BLACK", defaultColorStr);

    assertEquals(color, defaultColorStr);
}

Notez que ces méthodes sontnull-safe, c'est-à-dire ils peuvent gérer en toute sécurité le paramètre de cartenull:

@Test
public void whenGetOnNullMap_thenMustReturnDefaultValue() {
    String defaultColorStr = "COLOR_NOT_FOUND";
    String color = MapUtils.getString(null, "RED", defaultColorStr);

    assertEquals(color, defaultColorStr);
}

Ici, lescolor obtiendraient la valeurCOLOR_NOT_FOUND même si la carte estnull.

3.4. Inversion desMap

Nous pouvons également facilement inverser une carte:

@Test
public void whenInvertMap_thenMustReturnInvertedMap() {
    Map invColorMap = MapUtils.invertMap(this.colorMap);

    int size = invColorMap.size();
    Assertions.assertThat(invColorMap)
      .hasSameSizeAs(colorMap)
      .containsKeys(this.colorMap.values().toArray(new String[] {}))
      .containsValues(this.colorMap.keySet().toArray(new String[] {}));
}

Cela inverserait lescolorMap en:

{
    #00FF00 = GREEN
    #FF0000 = RED
    #0000FF = BLUE
}

Si la carte source associe la même valeur pour plusieurs clés, après inversion, l'une des valeurs deviendra une clé de manière aléatoire.

3.5. Chèques nuls et vides

La méthodeisEmpty() renvoietrue si unMap estnull ou vide.

La méthodesafeAddToMap() empêche l'ajout d'éléments nuls à unMap.

4. Décorateurs

Ces méthodes ajoutent des fonctionnalités supplémentaires à unMap.

Dans la plupart des cas, il est recommandé de ne pas stocker la référence à la carte décorée.

4.1. Taille fixeMap

fixedSizeMap() renvoie une carte de taille fixe soutenue par la carte donnée. Les éléments peuvent être modifiés mais non ajoutés ou supprimés:

@Test(expected = IllegalArgumentException.class)
public void whenCreateFixedSizedMapAndAdd_thenMustThrowException() {
    Map rgbMap = MapUtils
      .fixedSizeMap(MapUtils.putAll(new HashMap<>(), this.color1DArray));

    rgbMap.put("ORANGE", "#FFA500");
}

4.2. Map prédiqué

La méthodepredicatedMap() renvoie unMap garantit que tous les éléments conservés correspondent au prédicat fourni:

@Test(expected = IllegalArgumentException.class)
public void whenAddDuplicate_thenThrowException() {
    Map uniqValuesMap
      = MapUtils.predicatedMap(this.colorMap, null,
        PredicateUtils.uniquePredicate());

    uniqValuesMap.put("NEW_RED", "#FF0000");
}

Ici, nous avons spécifié le prédicat pour les valeurs en utilisantPredicateUtils.uniquePredicate(). Toute tentative d'insertion d'une valeur dupliquée dans cette carte entraînerajava.lang.IllegalArgumentException.

Nous pouvons implémenter des prédicats personnalisés en implémentant l'interfacePredicate.

4.3. ParesseuxMap

lazyMap() renvoie une carte où les valeurs sont initialisées à la demande.

Si une clé transmise à la méthodeMap.get(Object) de cette carte n’est pas présente dans la carte, l’instanceTransformer sera utilisée pour créer un nouvel objet qui sera associé à la clé demandée:

@Test
public void whenCreateLazyMap_theMapIsCreated() {
    Map intStrMap = MapUtils.lazyMap(
      new HashMap<>(),
      TransformerUtils.stringValueTransformer());

    assertThat(intStrMap, is(anEmptyMap()));

    intStrMap.get(1);
    intStrMap.get(2);
    intStrMap.get(3);

    assertThat(intStrMap, is(aMapWithSize(3)));
}

5. Conclusion

Dans ce rapide didacticiel, nous avons exploré la classe Apache Commons CollectionsMapUtils et nous avons examiné diverses méthodes utilitaires et décorateurs qui peuvent simplifier diverses opérations cartographiques courantes.

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