Comment filtrer un Map<String,Map<String,Employee>>
en utilisant Java 8 Filter?
Je dois filtrer uniquement lorsqu'un employé de la liste a une valeur de champ Gender = "M".
Contribution:
Map<String,Map<String,Employee>>
Sortie:
Map<String,Map<String,Employee>>
Critères de filtrage:
Employee.genter = "M"
De plus, je dois retourner une carte vide si le résultat filtré est vide.
J'ai essayé le ci-dessous, mais cela ne fonctionne pas comme prévu. Il retourne le seul si tous les employés sont avec le sexe "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));
Vous pouvez simplement itérer sur les paires clé-valeur et filtrer comme suit:
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)));
}
});
On dirait que ce que vous cherchez est donné un Entry<String,Map<String,Employee>>
s'il y a un employé qui a un sexe de "M" puis filtrez le Map<String,Employee>
intérieur pour ne contenir que les entrées avec un genre "M".
dans ce cas, vous pouvez filter
avec anyMatch
pour le premier critère. De plus, lors de la phase de collecte, vous pouvez appliquer le filtrage sur la carte interne:
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))));
La fonction allMatch
ne correspond que si chaque élément du flux correspond au prédicat; vous pouvez utiliser anyMatch
pour faire correspondre si un élément correspond au prédicat:
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));
Vous pouvez le faire comme ça,
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));
Prenez chaque entrée de carte de la carte externe et créez une nouvelle entrée de carte en utilisant la même clé et la carte imbriquée nouvellement construite avec la même clé et comportant uniquement des employés de sexe masculin. Enfin, collectez toutes les entrées correspondantes dans une nouvelle carte externe. Ceci gérera gracieusement le scénario vide que vous avez mentionné dans la déclaration de problème ci-dessus.
Une autre façon serait comme ça:
map.values()
.removeIf(entry->entry.values().stream().anyMatch(e -> !"M".equals(e.getGender())));
map.entrySet()
.removeIf(entry->entry.getValue().size() == 0);