Java 8 extract first key from matching value in a Map

Julian picture Julian · Jun 3, 2015 · Viewed 64.8k times · Source

Suppose I have a map of given name, surname pairs and I want to find the given name of the first entry in that map that has the surname matching a certain value. How would we do this in a java 8 fashion.

In my test case example below I put two ways that would do it.

However the first one (looking for the given name of the first person with a surname of "Donkey") will throw java.util.NoSuchElementException: No value present so it is not safe.

The second one works but it is not only harder to read but it it is a bit not quite functional.

Just wondering if someone here would suggest me an easier clearer way of achieving this using either stream() or forEach() or both.

@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);
}

Thank you in advance.

Answer

Misha picture Misha · Jun 3, 2015

To return a default value if there is no match, use Optional#orElse

names.entrySet().stream()
  .filter(e -> e.getValue().equals("Donkey"))
  .map(Map.Entry::getKey)
  .findFirst()
  .orElse(null);