1. введение
В этом кратком руководстве мы продемонстрируем три различных подхода к извлечению ключа из карты для заданного значения. Мы также обсудим положительные и отрицательные стороны различных решений.
Чтобы узнать больше об интерфейсе Map , вы можете прочитать эту статью .
2. Итеративный Подход
Интерфейс Map коллекций Java предлагает метод, называемый entrySet() . Он возвращает все записи или пары ключ-значение карты в наборе /.
Идея состоит в том, чтобы перебрать этот набор записей и вернуть ключ, для которого значение соответствует заданному значению:
publicK getKey(Map map, V value) { for (Entry entry : map.entrySet()) { if (entry.getValue().equals(value)) { return entry.getKey(); } } return null; }
Однако существует вероятность того, что несколько ключей указывают на одно и то же значение.
В этом случае, если найдено соответствующее значение, мы добавляем ключ в Set и продолжаем цикл. В конце концов, мы возвращаем Set , содержащий все нужные ключи:
publicSet getKeys(Map map, V value) { Set keys = new HashSet<>(); for (Entry entry : map.entrySet()) { if (entry.getValue().equals(value)) { keys.add(entry.getKey()); } } return keys; }
Хотя это очень простая реализация, она сравнивает все записи, даже если все совпадения найдены после нескольких итераций.
3. Функциональный Подход
С введением лямбда-выражений в Java 8 мы можем сделать это более гибким и читаемым способом. Мы преобразуем набор записей в Поток и предоставляем лямбду для фильтрации только тех записей с заданным значением.
Затем мы используем метод map для возврата потока ключей из отфильтрованных записей:
publicStream keys(Map map, V value) { return map .entrySet() .stream() .filter(entry -> value.equals(entry.getValue())) .map(Map.Entry::getKey); }
Преимущество возврата потока заключается в том, что он может удовлетворить широкий спектр потребностей клиентов. Для вызывающего кода может потребоваться только одна клавиша или все клавиши, указывающие на указанное значение. Поскольку оценка потока является ленивой, клиент может контролировать количество итераций на основе своих требований.
Кроме того, клиент может преобразовать поток в любую коллекцию, используя соответствующий коллектор:
StreamkeyStream1 = keys(capitalCountryMap, "South Africa"); String capital = keyStream1.findFirst().get(); Stream keyStream2 = keys(capitalCountryMap, "South Africa"); Set capitals = keyStream2.collect(Collectors.toSet());
4. Использование коллекций Apache Commons
Приведенные выше идеи были бы не очень полезны , если нам нужно очень часто вызывать функции для конкретной карты . Он будет без необходимости повторять набор своих ключей снова и снова.
В этом сценарии поддержание другой карты значений для ключей имело бы больше смысла, поскольку для извлечения ключа для значения потребуется постоянное время.
Библиотека Commons Collections от Apache предоставляет такую двунаправленную Карту под названием BidiMap . У него есть метод с именем get Key() для получения ключа для заданного значения:
BidiMapcapitalCountryMap = new DualHashBidiMap<>(); capitalCountryMap.put("Berlin", "Germany"); capitalCountryMap.put("Cape Town", "South Africa"); String capitalOfGermany = capitalCountryMap.getKey("Germany");
Однако BidiMap устанавливает соотношение 1:1 между своими ключами и значениями . Если мы попытаемся поместить пару ключ-значение, для которой значение уже существует в Карте, она удалит старую запись. Другими словами, он обновляет ключ в соответствии со значением.
Кроме того, для хранения обратной карты требуется больший объем памяти.
Более подробная информация о том, как использовать Растровое изображение содержится в этом руководстве .
5. Использование Google Guava
Мы можем использовать другую двунаправленную Карту под названием Bitmap , найденную в Гуаве, разработанной Google. Этот класс предоставляет метод с именем inverse() для получения ключа значения Map или обратного Map для извлечения ключа на основе заданного значения:
HashBiMapcapitalCountryMap = HashBiMap.create(); capitalCountryMap.put("Berlin", "Germany"); capitalCountryMap.put("Cape Town", "South Africa"); String capitalOfGermany = capitalCountryMap.inverse().get("Germany");
Как и BidiMap , BiMap также не позволяет использовать несколько ключей, ссылающихся на одно и то же значение . Если мы попытаемся сделать такую попытку, он выбросит java.lang.IllegalArgumentException .
Излишне говорить, Растровое изображение также используется значительный объем памяти, так как он должен хранить обратную карту внутри. Если вам интересно узнать больше о Растровое изображение , вы можете проверить этот учебник .
6. Заключение
В этой краткой статье мы обсудили некоторые методы извлечения ключа Карты с учетом значения. У каждого подхода есть свои плюсы и минусы. Мы всегда должны учитывать варианты использования и выбирать наиболее подходящий из них в зависимости от ситуации.
Полный исходный код для приведенного выше руководства доступен на GitHub .