1. Обзор
В этой статье мы рассмотрим одну из реализаций Map
из библиотеки Google Guava — Multimap
. Это коллекция, которая сопоставляет ключи со значениями, подобно java.util.Map
, но в которой каждый ключ может быть связан с несколькими значениями.
2. Зависимость от Maven
Сначала добавим зависимость:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
Последнюю версию можно найти здесь .
3. Реализация мультикарты
В случае с Guava Multimap,
если мы добавим два значения для одного и того же ключа, второе значение не переопределит первое значение. Вместо этого у нас будет два значения в результирующей карте
. Давайте посмотрим на тестовый пример:
String key = "a-key";
Multimap<String, String> map = ArrayListMultimap.create();
map.put(key, "firstValue");
map.put(key, "secondValue");
assertEquals(2, map.size());
Печать содержимого карты
выведет:
{a-key=[firstValue, secondValue]}
Когда мы будем получать значения по ключу «a-key», в результате мы получим Collection<String>
, содержащую «firstValue» и «secondValue»:
Collection<String> values = map.get(key);
При печати будут выводиться значения:
[firstValue, secondValue]
4. По сравнению со стандартной картой
Стандартная карта из пакета java.util
не дает нам возможности присваивать несколько значений одному и тому же ключу. Давайте рассмотрим простой случай, когда мы помещаем
два значения в Map
, используя один и тот же ключ:
String key = "a-key";
Map<String, String> map = new LinkedHashMap<>();
map.put(key, "firstValue");
map.put(key, "secondValue");
assertEquals(1, map.size());
Результирующая карта
имеет только один элемент ( «secondValue»)
из-за второй операции put()
, которая переопределяет первое значение. Если мы хотим добиться того же поведения, что и с Multimap в Guava
,
нам нужно создать карту
, которая имеет List<String>
в качестве типа значения:
String key = "a-key";
Map<String, List<String>> map = new LinkedHashMap<>();
List<String> values = map.get(key);
if(values == null) {
values = new LinkedList<>();
values.add("firstValue");
values.add("secondValue");
}
map.put(key, values);
assertEquals(1, map.size());
Понятно, что пользоваться им не очень удобно. И если у нас есть такая потребность в нашем коде, тогда Multimap
от Guava может быть лучшим выбором, чем java.util.Map.
Здесь следует отметить одну вещь: хотя у нас есть список, содержащий два элемента, метод size()
возвращает 1. В Multimap size()
возвращает фактическое количество значений, хранящихся в Map,
но keySet().size ()
возвращает количество различных ключей.
5. Плюсы Мультикарты
Мультикарты обычно используются в местах, где в противном случае появились бы Map<K, Collection<V>> .
Различия включают в себя:
- Нет необходимости заполнять пустую коллекцию перед добавлением записи с помощью
put() .
Метод get()
никогда не возвращаетnull
, а только пустую коллекцию (нам не нужно проверять значениеnull
, как в контрольном примереMap<String, Collection<V>> )
- Ключ содержится в
Multimap
тогда и только тогда, когда он соответствует хотя бы одному значению. Любая операция, которая приводит к тому, что ключ имеет нулевые связанные значения, приводит к удалению этого ключа изMultimap
(вMap<String, Collection<V>>,
даже если мы удаляем все значения из коллекции, мы по-прежнему сохраняем пустуюколлекцию
). как значение, и это ненужные накладные расходы памяти) - Общее количество входных значений доступно как
size()
6. Заключение
В этой статье показано, как и когда использовать Guava Multimap.
Он сравнивает его со стандартным java.util.Map
и показывает плюсы Guava Multimap.
Все эти примеры и фрагменты кода можно найти в проекте GitHub — это проект Maven, поэтому его легко импортировать и запускать как есть.