Вземете ключа за стойност от Java Map

1. Въведение

В този бърз урок ще демонстрираме три различни подхода за извличане на ключа от карта за дадена стойност. Ще обсъдим и положителните и отрицателните страни на различните решения.

За да научите повече за интерфейса на картата , можете да разгледате тази статия.

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

Най Карта интерфейс на Java Collections предлага метод, наречен entrySet () . Той връща всички записи или двойки ключ-стойност на картата в набор .

Идеята е да се направи итерация над този набор от записи и да се върне ключът, за който стойността съответства на предоставената стойност:

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

Въпреки това може да има вероятност множество ключове да сочат към една и съща стойност.

В този случай, ако бъде намерена съответстваща стойност, ние добавяме ключа към 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; }

Въпреки че това е много пряма реализация, тя сравнява всички записи, дори ако всички съвпадения са намерени след няколко повторения.

3. Функционален подход

С въвеждането на Lambda Expressions в Java 8 можем да го направим по по-гъвкав и четим начин. Преобразуваме набора от записи в поток и доставяме ламбда, за да филтрираме само тези записи с дадената стойност.

След това използваме метода map, за да върнем поток от ключове от филтрираните записи:

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

Предимството на връщането на поток е, че той може да отговори на широк спектър от нужди на клиента. Кодът за повикване може да изисква само един клавиш или всички клавиши, сочещи към предоставената стойност. Тъй като оценката на поток е мързелива, клиентът може да контролира броя на итерациите въз основа на неговите изисквания.

Освен това клиентът може да преобразува потока във всяка колекция, използвайки подходящ колектор:

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

Горните идеи не биха били много полезни, ако трябва да извикваме функциите много често за дадена карта . Той ще повтаря ненужно набора от ключове отново и отново.

В този сценарий поддържането на друга карта на стойността на ключовете би имало по-голям смисъл, тъй като отнема постоянно време за извличане на ключа за стойност.

В Commons Колекции библиотеката от Apache предоставя такъв двупосочен Карта нарича BidiMap . Той има метод на име getKey () за извличане на ключ за дадена стойност:

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

Въпреки това, BidiMap налага 1: 1 връзка между своите ключове и стойности . Ако се опитаме да поставим двойка ключ-стойност, за която стойността вече съществува в картата, тя премахва стария запис. С други думи, той актуализира ключа спрямо стойността.

Също така, той изисква по-голямо количество памет за поддържане на обратната карта.

Повече подробности за това как да използвате BidiMap са в този урок.

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

Можем да използваме друга двупосочна карта, наречена BiMap, намерена в Гуава, разработена от Google. Този клас предоставя метод, наречен inverse (), за да получи Map -key на стойност или обратната Map, за да извлече ключа въз основа на дадена стойност:

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

Подобно на BidiMap , BiMap също не позволява множество ключове, отнасящи се до една и съща стойност . Ако се опитаме да направим такъв опит, той хвърля java.lang.IllegalArgumentException .

Излишно е да казвам, че BiMap също използва значително количество памет, тъй като трябва да съхранява обратната карта вътре. Ако се интересувате да научите повече за BiMap , можете да разгледате този урок.

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

В тази кратка статия обсъдихме някои методи за извличане на ключ на карта, като се има предвид стойността. Всеки подход има своите плюсове и минуси. Винаги трябва да обмисляме случаите на употреба и да изберем най-подходящия в зависимост от ситуацията.

Пълният изходен код за горния урок е достъпен на GitHub.