Reputation: 107
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
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.
Upvotes: 0
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