Получить ключ для значения из карты Java

Получите Ключ для Значения от Карты Java

 

1. Вступление

In this quick tutorial, we’re going to demonstrate three different approaches for retrieving the key from a map for a given value. Мы также обсудим плюсы и минусы различных решений.

Чтобы узнать больше об интерфейсеMap, вы можете проверитьthis article.

2. Итеративный подход

ИнтерфейсMapJava Collections предлагает метод под названиемentrySet(). Он возвращает все записи или пары ключ-значение карты вSet.

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

public  K getKey(Map map, V value) {
    for (Entry entry : map.entrySet()) {
        if (entry.getValue().equals(value)) {
            return entry.getKey();
        }
    }
    return null;
}

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

В этом случае, если найдено совпадающее значение, мы добавляем ключ кSet и продолжаем цикл. В итоге мы возвращаемSet, содержащий все желаемые ключи:

public  Set 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;
}

Хотя это очень простая реализация,it compares all the entries even if all matches are found after a few iterations.

3. Функциональный подход

With the introduction of Lambda Expressions in Java 8, we can do it in a more flexible and readable way. Мы преобразуем набор записей вStream и предоставляем лямбда для фильтрации только тех записей с заданным значением.

Затем мы используем метод map, чтобы вернутьStream ключей из отфильтрованных записей:

public  Stream keys(Map map, V value) {
    return map
      .entrySet()
      .stream()
      .filter(entry -> value.equals(entry.getValue()))
      .map(Map.Entry::getKey);
}

The advantage of returning a stream is that it can cater to a wide range of client needs. Для вызывающего кода может потребоваться только один ключ или все ключи, указывающие на предоставленное значение. Поскольку оценка потока ленива, клиент может контролировать количество итераций в зависимости от своего требования.

Кроме того, клиент может преобразовать поток в любую коллекцию, используя соответствующий сборщик:

Stream keyStream1 = keys(capitalCountryMap, "South Africa");
String capital = keyStream1.findFirst().get();

Stream keyStream2 = keys(capitalCountryMap, "South Africa");
Set capitals = keyStream2.collect(Collectors.toSet());

4. Использование коллекций Apache Commons

Приведенные выше идеи не помогут,if we need to call the functions very frequently for a particular map. Он будет без необходимости повторять набор своих ключей снова и снова.

В этом сценарииmaintaining another map of value to the keys would make more sense as it will take constant time to retrieve the key for a value.

БиблиотекаCommons Collections отApache предоставляет такой двунаправленныйMap, называемыйBidiMap. У него есть метод с именемgetKey() для получения ключа для заданного значения:

BidiMap capitalCountryMap = new DualHashBidiMap<>();
capitalCountryMap.put("Berlin", "Germany");
capitalCountryMap.put("Cape Town", "South Africa");
String capitalOfGermany = capitalCountryMap.getKey("Germany");

ОднакоBidiMap imposes a 1:1 relationship between its keys and values. Если мы попытаемся поместить пару "ключ-значение", для которой значение уже существует вMap,, она удалит старую запись. Другими словами, он обновляет ключ в соответствии со значением.

Кроме того, для хранения обратной карты требуется больший объем памяти.

Более подробная информация о том, как использоватьBidiMap, находится вthis tutorial.

5. Использование Google Guava

We may use another bi-directional Map called BiMap found in Guava developed by Google. Этот класс предоставляет метод с именемinverse() для получения ключа значенияMap или обратныйMap для выборки ключа на основе заданного значения:

HashBiMap capitalCountryMap = HashBiMap.create();
capitalCountryMap.put("Berlin", "Germany");
capitalCountryMap.put("Cape Town", "South Africa");
String capitalOfGermany = capitalCountryMap.inverse().get("Germany");

КакBidiMap,BiMap also doesn’t allow multiple keys referring to the same value. Если мы попытаемся заставитьsuch an attempt, it выброситьjava.lang.IllegalArgumentException.

Излишне говорить, чтоBiMap также использует значительный объем памяти, поскольку он должен хранить внутри обратную карту. Если вам интересно узнать больше оBiMap, вы можете проверитьthis tutorial.

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

В этой краткой статье мы обсудили некоторые методы получения ключаMap’s с учетом значения. У каждого подхода есть свои плюсы и минусы. Мы всегда должны рассматривать варианты использования и выбирать наиболее подходящий в зависимости от ситуации.

Полный исходный код вышеупомянутого руководства доступенover on GitHub.