J'ai une Map
. Je dois d'abord être en mesure de filtrer les clés avec des nombres pairs, puis d'itérer les valeurs de la carte et de modifier le contenu des valeurs de la carte. J'ai essayé d'exécuter le code ci-dessous mais les valeurs ne changent pas. Est-il possible dans java 8 de modifier les valeurs en fonction d'une condition lors de l'itération d'une Map
?
Map<Integer,String> m = new HashMap<>(); m.put(1,"ABC"); m.put(2,"PQR"); m.put(3,"XYZ"); m.put(4,"RST"); Map<Integer,String> m1 = m.entrySet().stream() .filter(map -> map.getKey().intValue() %2 == 0) .collect(Collectors.toMap( map -> map.getKey(),map -> map.getValue())); Map<Integer,String> m3 = m1.entrySet().stream() .filter(m2 -> { if(m2.getValue().equalsIgnoreCase("PQR")){ m2.getValue().replace("PQR","PQR1"); } else if(m2.getValue().equalsIgnoreCase("RST")) { m2.getValue().replace("RST", "RST1"); } return true; }).collect(Collectors.toMap(m2 -> m2.getKey(), m2 -> m2.getValue())); System.out.println(m3);
La réponse que j'obtiens est {2 = PQR , 4 = RST}
mais ma réponse devrait se présenter sous la forme {2 = PQR1, 4 = RST1}
3 Réponses :
Le problème vient de la méthode replace
: comme une chaîne est immuable, cette méthode renvoie une nouvelle chaîne. Mais le code ignore cette valeur retournée.
pour une adaptation minimale de votre code, créez la carte m3
comme ceci:
Map<Integer,String> m3 = m1.entrySet().stream().map(m2 -> { if(m2.getValue().equalsIgnoreCase("PQR")){ m2.setValue("PQR1"); }else if(m2.getValue().equalsIgnoreCase("RST")) { m2.setValue("RST1"); } return m2; }).collect(Collectors.toMap(m2 -> m2.getKey(), m2 -> m2.getValue()));
Merci, cela a parfaitement fonctionné uniquement au lieu de renvoyer m2 doit retourner vrai
Non, car j'ai changé votre filtre
d'origine en carte
. Je ne pense pas que ce soit une bonne idée de changer la valeur de la méthode filter
.
La réponse que j'obtiens est {2 = PQR, 4 = RST} mais ma réponse devrait être {2 = PQR1, 4 = RST1}
Les chaînes sont immuables, vous ne définissez pas la nouvelle valeur de l'entrée. Vous devez créer une nouvelle entrée puis la collecter dans la
Map
:Map<String, String> helpMap = new HashMap<>(); // the replacement map helpMap.put("PQR", "PQR1"); helpMap.put("RST", "RST1"); Map<Integer, String> newMap = m.entrySet().stream() .filter(map -> map.getKey().intValue() %2 == 0) // only qualified keys .map(entry -> new AbstractMap.SimpleEntry<>( entry.getKey(), // key -> key replacementMap.getOrDefault( // lookup the value in helpMap entry.getValue(), // ... by the value as key entry.getValue()))) // ... or keep the original value .collect(Collectors.toMap( // collect back to Map<Integer,String> Map.Entry::getKey, // ... keys Map.Entry::getValue)); // ... values... ou en utilisant une simple
Map :: setValue
.Cependant, il existe un bien meilleur moyen. En gros, vous voulez:
- Filtrez ces entrées ayant une certaine
valeur
.- Modifier ces valeurs
L'API Stream est plutôt conçue pour fonctionner avec les
Collection
que lesMap
, mais elles sont quand même construites sur la collection. Il y a un moyen, un peu maladroit, mais c'est:.map(m2 -> new AbstractMap.SimpleEntry<>(m2.getKey(), m2.getValue().replace("PQR","PQR1")))Notes:
- La solution est basée sur le mappage des entrées chacune sur une nouvelle
Map.Entry
avec des valeurs modifiées, à partir de laquelle il est facile de compléter une nouvelleMap
en utilisant le bon collecteur .- Si la valeur de remplacement n'est pas trouvée dans
helpMap
, alors la valeur d'origine est utilisée - c'est à vous de décider. Vous pouvez filtrer ces valeurs invalides en utilisant.filter (entry -> replacementMap.containsKey (entry.getValue ()))
avant.map (..)
.
vous pouvez tout faire en une fois, filtrer les valeurs que vous souhaitez modifier et les rassembler sur une nouvelle carte comme:
Map<Integer, String> collect = m.entrySet().stream() .filter(e -> e.getKey() % 2 == 0) .peek(e -> { if (e.getValue().equalsIgnoreCase("PQR")) { e.setValue("PQR1"); } if (e.getValue().equalsIgnoreCase("RST")) { e.setValue("RST1"); } }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); System.out.println(collect);
Cela modifie la carte d'origine.