Java 8 Strem filter map in map — Map<String,Map<String,Employee>>

你。 提交于 2020-12-29 15:01:27

问题


How to filter a Map<String,Map<String,Employee>> using Java 8 Filter?

I have to filter only when any of employee in the list having a field value Gender = "M".

Input:

Map<String,Map<String,Employee>>

Output:

Map<String,Map<String,Employee>>

Filter criteria:

Employee.genter = "M"

Also i have to return empty map if the filtered result is empty.

I tried the below, but it is not working as expected. It is returning the only if all the Employees are with gender "M".

tempCollection.entrySet().stream()
                        .filter(i -> i.getValue().entrySet().stream().allMatch(e-> "M".equals(e.getValue().getGender())))
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

回答1:


You could simply iterate on the key-value pairs and filter as:

Map<String, Map<String, Employee>> output = new HashMap<>();
tempCollection.forEach((k, v) -> {
    if (v.values().stream().anyMatch(i -> "M".equals(i.getGender()))) {
        output.put(k, v.entrySet()
                .stream()
                .filter(i -> "M".equals(i.getValue().getGender()))
                .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)));
    }
});



回答2:


The function allMatch only matches if every element in the stream matches the predicate; you can use anyMatch to match if any element matches the predicate:

tempCollection.entrySet().stream()
                        .filter(i -> i.getValue().entrySet().stream().anyMatch(e-> "M".equals(e.getValue().getGender())))
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));



回答3:


Seems like what you're after is given a Entry<String,Map<String,Employee>> if there's any employee who has a gender of "M" then filter the inner Map<String,Employee> to contain only entries with a gender "M".

in which case you can filter along with anyMatch for the first criterion. Further, at the collecting phase, you can then apply the filtering on the inner map:

tempCollection.entrySet().stream()
            .filter(i -> i.getValue().values().stream().anyMatch(e -> "M".equals(e.getGender())))
            .collect(toMap(Map.Entry::getKey,
                    v -> v.getValue().entrySet().stream()
                            .filter(i -> "M".equals(i.getValue().getGender()))
                            .collect(toMap(Map.Entry::getKey, Map.Entry::getValue))));



回答4:


You may do it like so,

Map<String, Map<String, Employee>> maleEmpMap = tempCollection.entrySet().stream()
    .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(),
        e.getValue().entrySet().stream().filter(emp -> "M".equals(emp.getValue().getGender()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Take each map entry from the outer map and create a new map entry using the same key and the newly constructed nested map with the same key and which has only male employees as it's value. Finally collect all those matching entries into a new outer map. This will gracefully handle the empty scenario which you mentioned in the problem statement above.




回答5:


Other way would be like this:

map.values()
     .removeIf(entry->entry.values().stream().anyMatch(e -> !"M".equals(e.getGender())));

map.entrySet()
    .removeIf(entry->entry.getValue().size() == 0);


来源:https://stackoverflow.com/questions/53927656/java-8-strem-filter-map-in-map-mapstring-mapstring-employee

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!