Коллекции Apache Commons MapUtils

Коллекции Apache Commons MapUtils

1. Вступление

MapUtils - один из инструментов, доступных в проекте Apache Commons Collections.

Проще говоря, он предоставляет служебные методы и декораторы для работы с экземплярамиjava.util.Map иjava.util.SortedMap.

2. Настроить

Начнем с добавленияthe dependency:


    org.apache.commons
    commons-collections4
    4.1

3. Полезные методы

3.1. СозданиеMap изArray

Теперь давайте настроим массивы, которые мы будем использовать для создания карты:

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;

    //...
}

Давайте посмотрим, как мы можем создать карту из двумерного массива:

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

Мы также могли бы использовать одномерный массив. В этом случае массив обрабатывается как ключи и значения в альтернативных индексах:

@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. Печать содержимогоMap

Много раз во время отладки или в журналах отладки мы хотели бы напечатать всю карту:

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

И результат:

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

Мы также можем использоватьdebugPrint(), который дополнительно печатает типы данных значений.

3.3. Получение ценностей

MapUtils предоставляет некоторые методы для извлечения значения из карты для данного ключа безопасным дляnull способом.

Например,getString() получаетString отMap. ЗначениеString получается черезtoString(). При желании мы можем указать значение по умолчанию, которое будет возвращено, если значение равноnull или если преобразование не удалось:

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

    assertEquals(color, defaultColorStr);
}

Обратите внимание, что эти методы являютсяnull-безопасными, т.е. они могут безопасно обрабатывать параметр картыnull:

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

    assertEquals(color, defaultColorStr);
}

Здесьcolor получит значение какCOLOR_NOT_FOUND, даже если картаnull.

3.4. ИнвертированиеMap

Мы также можем легко перевернуть карту:

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

Это инвертируетcolorMap в:

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

Если исходная карта связывает одно и то же значение для нескольких ключей, то после инверсии одно из значений станет ключом случайным образом.

3.5. Нулевые и пустые проверки

МетодisEmpty() возвращаетtrue, еслиMap равноnull или пусто.

МетодsafeAddToMap() предотвращает добавление нулевых элементов вMap.

4. Декораторы

Эти методы добавляют дополнительную функциональность кMap.

В большинстве случаев рекомендуется не хранить ссылку на оформленную карту..

4.1. Фиксированный размерMap

fixedSizeMap() возвращает карту фиксированного размера, поддерживаемую данной картой. Элементы могут быть изменены, но не могут быть добавлены или удалены:

@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

МетодpredicatedMap() возвращаетMap гарантирует, что все удерживаемые элементы соответствуют предоставленному предикату:

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

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

Здесь мы указали предикат для значений с помощьюPredicateUtils.uniquePredicate(). Любая попытка вставить повторяющееся значение в эту карту приведет кjava.lang.IllegalArgumentException.

Мы можем реализовать собственные предикаты, реализовав интерфейсPredicate.

4.3. ЛенивыйMap

lazyMap() возвращает карту, где значения инициализируются по запросу.

Если ключ, переданный методуMap.get(Object) этой карты, отсутствует на карте, экземплярTransformer будет использоваться для создания нового объекта, который будет связан с запрошенным ключом:

@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. Заключение

В этом кратком руководстве мы изучили класс Apache Commons CollectionsMapUtils и рассмотрели различные служебные методы и декораторы, которые могут упростить различные общие операции с картами.

Как обычно, доступен кодover on GitHub.