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 :
MultiValuedMapmap = 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 представление ключей:
MultiSetkeys = map.keys(); assertThat(keys).contains("fruits", "vehicles");
В качестве альтернативы мы можем получить Set представление ключей с помощью метода keySet :
Setkeys = map.keySet(); assertThat(keys).contains("fruits", "vehicles");
4.4. Получить все значения Карты
Наконец, если мы хотим получить Collection представление всех значений, содержащихся на карте, мы можем использовать метод values :
Collectionvalues = map.values(); assertThat(values).contains("apple", "orange", "car", "bike");
5. Удаление элементов из многозначной карты
Теперь давайте рассмотрим все методы удаления элементов и сопоставления ключ-значение.
5.1. Удалите все элементы, сопоставленные Ключу
Во-первых, давайте посмотрим, как удалить все значения, связанные с указанным ключом, с помощью метода remove :
CollectionremovedValues = 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 внутренне для хранения значений, связанных с каждым ключом, поэтому он позволяет дублировать пары ключ-значение :
MultiValuedMapmap = 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 для хранения значений для каждого заданного ключа. Поэтому он не допускает дублирования пар ключ-значение .
Давайте рассмотрим быстрый пример, где мы дважды добавляем одно и то же сопоставление ключ-значение:
MultiValuedMapmap = 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() { MultiValuedMapmap = 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 .