Откройте для себя более безопасную альтернативу сопоставлению ключей с несколькими значениями в Java.

Мне нужна карта с несколькими значениями

В какой-то момент за годы написания кода на Java вам, вероятно, понадобился файл Map<K, Collection<V>>. Если он вам еще не нужен, дайте ему время… он вам понадобится. Существуют более удобные способы управления Collection частью Map с помощью методов, доступных начиная с Java 8. Если вы никогда раньше не использовали computeIfAbsent, этот метод стоит изучить. Ниже приведен пример создания Map<String, List<String>> с использованием computeIfAbsent.

Принцип работы computeIfAbsent прост. Во-первых, он ищет на карте указанный ключ (например, «A»). Если он не находит значение по ключу, он оценивает указанный Function и сохраняет результат в файле Map. Затем он возвращает либо найденное значение, либо значение, созданное и сохраненное в файле Map. Таким образом, в основном, computeIfAbsent - это get с put, где значение put в Map возвращается методом. Этот метод гарантирует, что значение всегда существует для любого искомого ключа, но может быть расточительным в качестве замены get, поскольку он всегда будет приводить к put в тех случаях, когда вы ищете ключ, который не существует.

Карта имеет нулевую проблему

Одна проблема с использованием Map заключается в том, что такие реализации, как HashMap, допускают null ключей, значений и возвратов. Если мы проигнорируем нулевые ключи на секунду, проблема со значениями и возвратами null заключается в том, что если вы ищете ключ, который не существует в Map, вы получите обратно null. Вы можете попытаться защитить свой код от возможности проверки того, что Map возвращает null при вызове get, или с помощью более безопасного метода, такого как getOrDefault, который может возвращать пустую коллекцию в случае многозначного Map по умолчанию. Реальным решением было бы создать тип Map, который знает, что отсутствующий ключ должен привести к возврату пустого Collection при вызове get. Это то, что делает Multimap.

Не шутите с Картами с несколькими значениями

Если вам нужна многозначная поддержка Map, рассмотрите возможность использования типа Multimap из библиотеки, такой как Eclipse Collections, Google Guava или Apache Commons Collections. Метод put для Multimap будет знать, что значения являются многозначными, и должен автоматически вызывать add для контейнеров значений. Метод get для Multimap знает, когда ключ не содержится в Multimap, и вместо этого следует вернуть пустой Collection. Дело в том, что Multimap имеет более глубокие знания о типе значения, которым он управляет. Map может быть предоставлен тип значения через дженерики, но он не знает, что тип значения должен быть типом Collection.

Использование Multimap в Eclipse Collections

В следующем коде показано решение, эквивалентное приведенному выше коду Map, с использованием типа Multimap из Eclipse Collections.

Во-первых, я создаю определенный тип Multimap, который в данном случае является MutableListMultimap. Затем я могу просто вызвать put с каждым ключом и значением. Multimap знает, что нужно создать резервный контейнер Collection (в данном случае MutableList) для каждого нового ключа. Наконец, вызов multimap.get(“D”) возвращает пустой List. Этот List не хранится в Multimap, поэтому Multimap останется разреженным и будет содержать только ключи с фактическими значениями.

Типы мультикарт в Eclipse Collections

В Eclipse Collections есть несколько конкретных типов Multimap. Есть интерфейсы Readable, Mutable и Immutable. Multimap — это родительский интерфейс. MutableListMultimap — это листовой интерфейс. Ниже приведены примеры основных типов бетона Multimap, которые можно создать с помощью фабрики Multimaps.

Для Multimap существуют определенные типы, основанные на контейнерах значений (например, List, Set, Bag). Для этих типов могут существовать специализации, а иногда и оптимизации.

GroupBy должен возвращать Multimap

Eclipse Collections — это единственная библиотека Java, о которой я знаю на сегодняшний день, которая возвращает Multimap из своих groupBy методов для каждого из своих основных Collection типов. Каждый конкретный тип, такой как MutableList или MutableSet, будет возвращать соответствующий тип Multimap в своем методе groupBy на основе своего типа. MutableList возвращает MutableListMultimap из своего метода groupBy, а MutableSet возвращает MutableSetMultimap. Ниже приведен пример использования groupBy в Eclipse Collections.

Дополнительные примеры groupBy можно найти в следующем блоге.



Дополнительная информация о мультикарте коллекций Eclipse

Нихил Нанивадекар несколько лет назад написал блог о Multimaps в Eclipse Collections. Он дает более подробные объяснения реализации.



Краткое содержание

Вам нужна карта с поддержкой ключей и нескольких значений? Рассмотрите возможность использования Multimap из коллекций Eclipse. Если вы уже используете другие типы Collection из коллекций Eclipse, методы groupBy предоставят вам простой доступ к созданию соответствующих типов Multimap.

Я являюсь руководителем и ответственным за проект OSS Eclipse Collections в Eclipse Foundation. Eclipse Collections открыт для пожертвований. Если вам нравится библиотека, сообщите нам об этом, пометив ее звездочкой на GitHub.

Другие статьи по Java, которые могут вам понравиться