Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 extract first key from matching value in a Map

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.

like image 581
Julian Avatar asked Jun 02 '15 23:06

Julian


People also ask

Can we get key from value in map?

Get keys from value in HashMap To find all the keys that map to a certain value, we can loop the entrySet() and Objects. equals to compare the value and get the key. The common mistake is use the entry. getValue().

Can we get key from value in HashMap?

If your hashmap contain unique key to unique value mapping, you can maintain one more hashmap that contain mapping from Value to Key. In that case you can use second hashmap to get key.

How do I find the first element of a map?

To get the first element of a Map , use destructuring assignment, e.g. const [firstKey] = map. keys() and const [firstValue] = map. values() . The keys() and values() methods return an iterator object that contains the Map's keys and values.

How do you get a key value pair on a map?

Get Keys and Values (Entries) from Java MapThe entrySet() method returns a set of Map. Entry<K, V> objects that reside in the map. You can easily iterate over this set to get the keys and their associated values from a map.


2 Answers

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); 
like image 172
Misha Avatar answered Oct 18 '22 00:10

Misha


From a similar question:

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

Then you can select the first, if you want to. Remember that the key is unique, the value is not.

Edit: The whole code (thanks @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());
        }
    }
}
like image 32
Doon Avatar answered Oct 18 '22 02:10

Doon