Prashanth
Prashanth

Reputation: 107

java 8 - Way to filter list of values from a map?

I have a map

Map<Integer, List<Person>> personsById

and a predicate function callbak

(person) -> person.getPersonID() > 10 && person.blabla() !=null

I need to filter the map based on the predicate and I came up with below code which doesn't modify the List

map.entrySet().stream()
.filter(entry -> entry.getValue().stream().anyMatch(predicate))
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue))

However the above code doesnt actually filter the List ext: {id: 100, [{personID: 100}, {personID: 50}, {personID: 2}] I can still seee personID: 2 in the list. Is there a way I can modify the value in the list to return filtered List or persons?. Any pointers on it in java 8 will be greatly useful.

P.s: Plz ignore any typos in the typed code I came up with.

Edit: I got the answer

map.entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey,
                        entry -> entry.getValue().stream().filter(predicate).collect(Collectors.toList())))

Upvotes: 2

Views: 7152

Answers (2)

Lino
Lino

Reputation: 19910

If you don't care about you're inital map then you can use following snippet, which iterates over the values stored in the map and then checks if an item in the list needs to be removed when it doesn't fullfil the predicate:

map.values().forEach(list -> list.removeIf(predicate.negate()));

What i have to mention though is, that this works only for mutable lists. For imutable ones an unchecked UnsupportedOperationException is thrown at runtime.

Doc: Collection.removeIf(Predicate)

Upvotes: 0

Prashanth
Prashanth

Reputation: 107

I found the below approach to be working well for me. Any better solutions are welcome to post a reply and say why its better. Currently, this code returns a map keys with an empty list if no match is found, (If you have a solution which can eliminate keys from the result and return null when nothing matches that will be good too).

             map.entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey,
                  entry -> entry.getValue()
                               .stream().filter(predicate)
                               .collect(Collectors.toList()))
                 )

Upvotes: 3

Related Questions