Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I search a map in Java for a key that matches a predicate?

Tags:

java

java-8

Do I understand this correctly? Is this how Java developers do it? Or is there a better way?

So if I want to find a key in a map that matches a predicate, I must first get the key set from the map through the conveniently supplied method. THEN, I have to convert the set into a stream through the conveniently supplied method. THEN, I have to filter the stream with my predicate through the conveniently supplied method. THEN, I have to convert the stream into a container of a type of my choosing, possibly supplying a collector to do so, through the conveniently supplied method. THEN, I can at least check the container for empty to know if anything matched. Only then can I use the key(s) to extract the values of interest, or I could have used the entry set from the beginning and spare myself the extra step.

Is this the way, really? Because as far as I can tell, there are no other methods either built into the map or provided as a generic search algorithm over iterators or some other container abstraction.

like image 624
Matthew Reddington Avatar asked Sep 15 '16 18:09

Matthew Reddington


2 Answers

I prefer entrySet myself as well. You should find this efficient:

Map<String, Integer> map; //Some example Map
//The map is filled here

List<Integer> valuesOfInterest = map.entrySet()
                                 .stream() //Or parallelStream for big maps
                                 .filter(e -> e.getKey().startsWIth("word")) //Or some predicate
                                 .map(Map.Entry::getValue) //Get the values
                                 .collect(Collectors.toList()); //Put them in a list

The list is empty if nothing matched. This is useful if multiple keys match the predicate.

like image 80
Zircon Avatar answered Nov 15 '22 01:11

Zircon


In a nutshell, it is as simple as:

Predicate<T> predicate = (t -> <your predicate here>);
return myMap.keySet()
    .stream()
    .filter(predicate)
    .findAny()
    .map(myMap::get);

returns an empty Optional if no key matches

(nota: findAny is better than findFirst because it does not prevent parallelization if relevant, and findFirst is useless anyway since the Set of keys is not sorted in any meaningful way, unless your Map is a SortedMap)

like image 42
njzk2 Avatar answered Nov 15 '22 00:11

njzk2