Ответ 1
Чтобы вернуть значение по умолчанию, если нет совпадения, используйте Optional#orElse
names.entrySet().stream()
.filter(e -> e.getValue().equals("Donkey"))
.map(Map.Entry::getKey)
.findFirst()
.orElse(null);
Предположим, что у меня есть карта заданного имени, фамилии, и я хочу найти заданное имя первой записи на той карте, у которой есть фамилия, соответствующая определенному значению. Как мы будем делать это с использованием java 8.
В приведенном ниже примере тестового примера я делаю два способа сделать это.
Однако первый (ищет имя первого человека с фамилией "Осел" ) будет бросать java.util.NoSuchElementException: нет значения, чтобы оно было безопасным.
Второй работает, но читать его не только труднее, но и немного не совсем функционально.
Просто интересно, может ли кто-нибудь предложить мне более простой способ достичь этого, используя либо stream()
, либо forEach()
, либо оба.
@Test
public void shouldBeAbleToReturnTheKeyOfTheFirstMatchingValue() throws Exception {
Map<String, String> names = new LinkedHashMap<>();
names.put("John", "Doe");
names.put("Fred", "Flintstone");
names.put("Jane", "Doe");
String keyOfTheFirst = names.entrySet().stream().filter(e -> e.getValue().equals("Doe")).findFirst().get().getKey();
assertEquals("John", keyOfTheFirst);
try {
names.entrySet().stream().filter(e -> e.getValue().equals("Donkey")).findFirst().get();
} catch (NoSuchElementException e){
// Expected
}
Optional<Map.Entry<String, String>> optionalEntry = names.entrySet().stream().filter(e -> e.getValue().equals("Donkey")).findFirst();
keyOfTheFirst = optionalEntry.isPresent() ? optionalEntry.get().getKey() : null;
assertNull(keyOfTheFirst);
}
Спасибо заранее.
Чтобы вернуть значение по умолчанию, если нет совпадения, используйте Optional#orElse
names.entrySet().stream()
.filter(e -> e.getValue().equals("Donkey"))
.map(Map.Entry::getKey)
.findFirst()
.orElse(null);
Решение, предоставляемое @Misha, является лучшим, если вы не хотите использовать сторонний код. Моя библиотека имеет специальный метод быстрого доступа ofKeys
для таких когда я обнаружил, что это довольно общая задача:
StreamEx.ofKeys(names, "Donkey"::equals).findFirst().orElse(null);
Из аналогичного вопроса :
public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
return map.entrySet()
.stream()
.filter(entry -> Objects.equals(entry.getValue(), value))
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
Затем вы можете выбрать первый, если хотите. Помните, что key
уникален, value
не является.
Изменить: Весь код (спасибо @Peter Lawrey)
package test;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
public class Main {
public static void main(String[] args) {
Map<String, String> names = new LinkedHashMap<>();
names.put("John", "Doe");
names.put("Fred", "Flintstone");
names.put("Jane", "Doe");
Optional<String> firstKey = names.entrySet().stream()
.filter(entry -> Objects.equals(entry.getValue(), "Doe"))
.map(Map.Entry::getKey).findFirst();
if (firstKey.isPresent()) {
System.out.println(firstKey.get());
}
}
}
Мне нравится старомодный:
static <K, V> K findFirstKeyByValue(Map<K, V> map, String value) {
for (Entry<K, V> e : map.entrySet())
if (e.getValue().equals(value))
return e.getKey();
return null;
}
Ниже приведен мой фрагмент кода, чтобы получить ключ от карты,
Map<String,String> pageDetails = new HashMap<String,String>();
public String getAssociatedKey(){
pageDetails.entrySet().stream().filter( e -> e.getValue().contains("John").findFirst().get().getKey();
}
Чтобы избежать исключения нулевого указателя, если запись карты существует с нулевым значением:
private String getValueByKey (Карта, ключ строки) {return map.entrySet(). stream(). filter (e → StringUtils.equalsIgnoreCase(e.getKey(), key)). findFirst(). get().getValue(); } }