NyanNyanMusume
NyanNyanMusume

Reputation: 31

How to find a key in a HashMap that is mapped to a List<String> value containing the given string

I have a map with a pet owner's name for key and a List of pets for a value.

I want to get the names of the people who have a hamster.

Map<String, List<String>> map = new HashMap<>();
List<String> list = new ArrayList<>();

list.add("dog");
map.put("Pesho", list);

list.clear();
list.add("dog");
list.add("cat");
map.put("Anne", list);

list.clear();
list.add("iguana");
list.add("hamster");
list.add("turtle");
map.put("Kate", list);

 // The stream only returns if someone in the map has a hamster
System.out.println(map.values().stream()
                      .anyMatch(pets -> pets.contains("hamster"))); 

Upvotes: 3

Views: 2036

Answers (1)

Alexander Ivanchenko
Alexander Ivanchenko

Reputation: 28978

Iteration needs to be done over the entry set or over the key set, it is impossible to access a key when have only a value.

Operation anyMatch() returns a boolean value. You need to use either findFirst() to get a single result, or collect() to obtain a collection of names. In both cases, the predicate from the anyMatch() needs to be placed into the filter() operation.

Terminal operation findFirst() returns Optional because a result might not be present. You can extract a value from the optional in different ways, for instance, by applying get(), but in the case of empty optional it'll throw NoSuchElementException. In the example below, method orElse() is used to provide a default value.

String name =
        map.entrySet().stream() // stream of map-entries
                    .filter(entry -> entry.getValue().contains("hamster"))
                    .map(Map.Entry::getKey)
                    .findFirst()
                    .orElse("no owner was found");

Operation collect() expects as a parameter Collector (an object that is responsible for populating a mutable container, like a collection with elements of the stream).

List<String> names =
       map.keySet().stream() // stream of owner names
                   .filter(key -> map.get(key).contains("hamster"))
                   .collect(Collectors.toList());  // Or `toList()` in Java 16+.

Note:

  • When the two entries in your code will share the same list. Instead of invoking list.clear(); need to create a new list so that every key will correspond to a distinct collection of pet-names.
  • Search will be more performant if you replace an ArrayList with a HashSet (i.e. map will be declared as Map<String,Set<String>>).

Upvotes: 3

Related Questions