1
votes

Pouvons-nous modifier les valeurs de la carte lors de l'itération dans Java 8

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}


0 commentaires

3 Réponses :


0
votes

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


2 commentaires

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 .



0
votes

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 les Map , 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 nouvelle Map 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 (..) .

0 commentaires

0
votes

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


1 commentaires

Cela modifie la carte d'origine.