简体   繁体   English

Java 8 Strem过滤地图在地图中 - Map <String,Map <String,Employee >>

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

How to filter a Map<String,Map<String,Employee>> using Java 8 Filter? 如何使用Java 8 Filter过滤Map<String,Map<String,Employee>>

I have to filter only when any of employee in the list having a field value Gender = "M". 我必须仅在列表中具有字段值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". 如果所有员工都是性别“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));

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)));
    }
});

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". 如果有任何员工的性别为“M”,则过滤内部Map<String,Employee>以仅包含具有性别的条目,看起来像您所获得的Entry<String,Map<String,Employee>> “M”。

in which case you can filter along with anyMatch for the first criterion. 在这种情况下,您可以与anyMatch一起filter第一个标准。 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))));

The function allMatch only matches if every element in the stream matches the predicate; 函数allMatch仅匹配流中的每个元素与谓词匹配; you can use anyMatch to match if any element matches the predicate: 如果任何元素与谓词匹配,您可以使用anyMatch匹配:

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));

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. 这将优雅地处理您在上面的问题陈述中提到的空场景。

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM