Рубрики
Без рубрики

Руководство по Apache Commons MultivaluedMap

Узнайте, как использовать MultivaluedMap из библиотеки Apache Commons Collections для сопоставления каждого ключа с коллекцией значений в Java.

Автор оригинала: baeldung.

1. Обзор

В этом кратком руководстве мы рассмотрим интерфейс MultivaluedMap , предоставляемый в библиотеке Apache Commons Collections library .

MultivaluedMap предоставляет простой API для сопоставления каждого ключа с коллекцией значений в Java. Это преемник org.apache.commons.collections4.MultiMap , который был устаревшим в Commons Collection 4.1.

2. Зависимость Maven

Для проектов Maven нам нужно добавить зависимость commons-collections4 :


    org.apache.commons
    commons-collections4
    4.2

3. Добавление элементов в многозначную карту

Мы можем добавлять элементы с помощью методов put и putAll .

Давайте начнем с создания экземпляра MultivaluedMap :

MultiValuedMap map = new ArrayListValuedHashMap<>();

Далее давайте посмотрим, как мы можем добавлять элементы по одному с помощью метода put :

map.put("fruits", "apple");
map.put("fruits", "orange");

Кроме того, давайте добавим некоторые элементы с помощью метода putAll , который сопоставляет ключ нескольким элементам в одном вызове:

map.putAll("vehicles", Arrays.asList("car", "bike"));
assertThat((Collection) map.get("vehicles"))
  .containsExactly("car", "bike");

4. Извлечение элементов из многозначной карты

MultivaluedMap предоставляет методы для извлечения ключей, значений и сопоставлений ключ-значение. Давайте взглянем на каждый из них.

4.1. Получить все значения ключа

Чтобы получить все значения, связанные с ключом, мы можем использовать метод get , который возвращает коллекцию :

assertThat((Collection) map.get("fruits"))
  .containsExactly("apple", "orange");

4.2. Получить Все Сопоставления Ключ-Значение

Или мы можем использовать метод entries для получения Коллекции всех отображений ключ-значение, содержащихся в карте:

Collection> entries = map.entries();

4.3. Получить Все Ключи

Существует два метода извлечения всех ключей, содержащихся в многозначной карте .

Давайте используем метод keys , чтобы получить MultiSet представление ключей:

MultiSet keys = map.keys();
assertThat(keys).contains("fruits", "vehicles");

В качестве альтернативы мы можем получить Set представление ключей с помощью метода keySet :

Set keys = map.keySet();
assertThat(keys).contains("fruits", "vehicles");

4.4. Получить все значения Карты

Наконец, если мы хотим получить Collection представление всех значений, содержащихся на карте, мы можем использовать метод values :

Collection values = map.values();
assertThat(values).contains("apple", "orange", "car", "bike");

5. Удаление элементов из многозначной карты

Теперь давайте рассмотрим все методы удаления элементов и сопоставления ключ-значение.

5.1. Удалите все элементы, сопоставленные Ключу

Во-первых, давайте посмотрим, как удалить все значения, связанные с указанным ключом, с помощью метода remove :

Collection removedValues = map.remove("fruits");
assertThat(map.containsKey("fruits")).isFalse();
assertThat(removedValues).contains("apple", "orange");

Этот метод возвращает представление Collection удаленных значений.

5.2. Удаление одного сопоставления Ключ-значение

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

boolean isRemoved = map.removeMapping("fruits","apple");
assertThat(map.containsMapping("fruits","apple")).isFalse();

5.3. Удалите Все Сопоставления Ключ-Значение

И, наконец, мы можем использовать метод clear для удаления всех отображений с карты:

map.clear();
assertThat(map.isEmpty()).isTrue();

6. Проверка элементов из многозначной карты

Далее давайте рассмотрим различные методы проверки того, существует ли указанный ключ или значение в нашей карте.

6.1. Проверьте, Существует ли Ключ

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

assertThat(map.containsKey("vehicles")).isTrue();

6.2. Проверьте, Существует Ли Значение

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

assertThat(map.containsValue("orange")).isTrue();

6.3. Проверьте, Существует ли Сопоставление Ключ-Значение

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

assertThat(map.containsMapping("fruits","orange")).isTrue();

6.4. Проверьте, Пуста Ли Карта

Чтобы проверить, не содержит ли карта вообще никаких сопоставлений ключ-значение, мы можем использовать метод isEmpty :

assertThat(map.isEmpty()).isFalse;

6.5. Проверьте размер карты

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

assertEquals(4, map.size());

7. Реализация

Библиотека Apache Commons Collections также предоставляет несколько реализаций этого интерфейса. Давайте взглянем на них.

7.1. ArrayListValuedHashMap

An ArrayListValuedHashMap использует ArrayList внутренне для хранения значений, связанных с каждым ключом, поэтому он позволяет дублировать пары ключ-значение :

MultiValuedMap map = new ArrayListValuedHashMap<>();
map.put("fruits", "apple");
map.put("fruits", "orange");
map.put("fruits", "orange");
assertThat((Collection) map.get("fruits"))
  .containsExactly("apple", "orange", "orange");

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

7.2. HashSetValuedHashMap

A HashSetValuedHashMap использует a HashSet для хранения значений для каждого заданного ключа. Поэтому он не допускает дублирования пар ключ-значение .

Давайте рассмотрим быстрый пример, где мы дважды добавляем одно и то же сопоставление ключ-значение:

MultiValuedMap map = new HashSetValuedHashMap<>();
map.put("fruits", "apple");
map.put("fruits", "apple");
assertThat((Collection) map.get("fruits"))
  .containsExactly("apple");

Обратите внимание, что, в отличие от нашего предыдущего примера, который использовал ArrayListValuedHashMap, реализация HashSetValuedHashMap игнорирует дублирующее отображение.

Класс HashSetValuedHashMap также не является потокобезопасным .

7.3. UnmodifiableMultiValuedMap

UnmodifiableMultiValuedMap – это класс декоратора, который полезен, когда нам нужен неизменяемый экземпляр MultivaluedMap – то есть он не должен допускать дальнейших модификаций:

@Test(expected = UnsupportedOperationException.class)
public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() {
    MultiValuedMap map = new ArrayListValuedHashMap<>();
    map.put("fruits", "apple");
    map.put("fruits", "orange");
    MultiValuedMap immutableMap =
      MultiMapUtils.unmodifiableMultiValuedMap(map);
    immutableMap.put("fruits", "banana"); // throws exception
}

И опять же, стоит отметить, что изменение final out приведет к UnsupportedOperationException .

8. Заключение

Мы видели различные методы интерфейса MultivaluedMap из библиотеки Apache Commons Collections. Кроме того, мы изучили несколько популярных реализаций.

И, как всегда, полный исходный код доступен на Github .