地图中的 Java 8 流过滤器地图 -- Map<String,Map<String,Employee>>
Posted
技术标签:
【中文标题】地图中的 Java 8 流过滤器地图 -- Map<String,Map<String,Employee>>【英文标题】:Java 8 Strem filter map in map -- Map<String,Map<String,Employee>> 【发布时间】:2019-05-24 10:57:33 【问题描述】:如何使用 Java 8 过滤器过滤 Map<String,Map<String,Employee>>
?
只有当列表中的任何员工具有字段值 Gender = "M" 时,我才需要过滤。
输入:
Map<String,Map<String,Employee>>
输出:
Map<String,Map<String,Employee>>
过滤条件:
Employee.genter = "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));
【问题讨论】:
返回所有性别为M的员工。 【参考方案1】:您可以简单地迭代键值对并过滤为:
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)));
);
【讨论】:
anyMatch 即使只有一个匹配项也会返回所有结果,如果没有匹配项,我希望删除键值, 如果没有一个员工的性别为“M”,它仍然返回 Mapput
比putIfAbsent
更理想,因为key
总是独一无二的。【参考方案2】:
函数allMatch
仅在流中的每个元素都与谓词匹配时才匹配;如果有任何元素与谓词匹配,则可以使用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));
【讨论】:
【参考方案3】:如果有任何员工的性别为“M”,那么您所追求的似乎是Entry<String,Map<String,Employee>>
,然后过滤内部Map<String,Employee>
以仅包含性别为“M”的条目。
在这种情况下,您可以将filter
与anyMatch
一起作为第一个条件。此外,在收集阶段,您可以在内部地图上应用过滤:
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))));
【讨论】:
anyMatch 会返回地图中的所有值,即使只有一名员工的性别为 M。 @user1578872 对,感谢接受的答案,我现在可以理解您的要求。 IMO 的描述不是很清楚。无论如何编辑以适应。【参考方案4】:你可以这样做,
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));
从外部映射中获取每个映射条目,并使用相同的键创建一个新的映射条目,并使用相同的键和新构建的嵌套映射创建一个新的映射条目,其中只有男性员工作为它的值。最后将所有匹配的条目收集到一个新的外部映射中。这将优雅地处理您在上面的问题陈述中提到的空场景。
【讨论】:
【参考方案5】:其他方式是这样的:
map.values()
.removeIf(entry->entry.values().stream().anyMatch(e -> !"M".equals(e.getGender())));
map.entrySet()
.removeIf(entry->entry.getValue().size() == 0);
【讨论】:
以上是关于地图中的 Java 8 流过滤器地图 -- Map<String,Map<String,Employee>>的主要内容,如果未能解决你的问题,请参考以下文章
Java 8,流过滤器,反射,NoSuchMethodException [重复]