4
votes

Modèle pour diviser la chaîne et stocker dans HashMap Java 8

Je veux diviser la chaîne ci-dessous et la stocker dans un HashMap:

Map<String,String> mapVal= null;
mapVal = Pattern.compile("\\s*=\\s*")
                .splitAsStream(currentString.trim())
                .map(s -> s.split("-", 2))
                .collect(Collectors.toMap(a -> a[0], a -> a.length>1? a[1]: ""));

Je veux que ma sortie soit stockée dans la carte, comme la première chaîne avant le trait d'union (-) (firstName) et première chaîne après (=) (firstName1), ......... ie,

{firstName=firstName1,lastName=lastName1,rollNum=rollNum1,departmentNum=departmentNum1}

Le code ci-dessous ne fonctionne pas pour mon modèle:

String currentString= "firstName-lastName-rollNum-departmentNum=firstName1-lastName1-rollNum1-departmentNum1"; 

Une fois que j'ai divisé la chaîne, je ne comprends pas comment je peux rassembler mes valeurs requises comme indiqué ci-dessus. Je m'excuse si vous ne recevez pas ma question.

Merci d'avance !!


0 commentaires

5 Réponses :


7
votes

Une approche plus simple consiste simplement à utiliser la division avec des tableaux standard.

String[] keyValues = currentString.split("=", 2);
String[] keys = keyValues[0].split("-");
String[] values = keyValues[1].split("-", keys.length);
Map<String, String> map = IntStream.range(0, keys.length).boxed()
        .collect(Collectors.toMap(i -> keys[i], i -> values[i]));

Il n'y a pas de vérification d'erreur mais j'espère que cela vous donnera une idée générale.

p >


0 commentaires

2
votes

Autre solution:

String[] arr = Arrays.toString(currentString.split("="))
                     .replaceAll("[\\[\\]]", "").replaceAll(",", "-")
                     .split("-");

Map<String, String> collect = IntStream.range(0, arr.length / 2).boxed()
                 .collect(Collectors.toMap(i -> arr[i], i -> arr[i + arr.length / 2]));

Ici, nous divisons d'abord la chaîne en fonction de = , puis nous utilisons le .toString () pour supprimez toutes les occurrences de ] et [ de la chaîne. Maintenant, nous remplaçons , par - afin que nous puissions diviser la chaîne résultante en fonction de -

Après la première instruction, le tableau arr ressemble à:

[firstName, lastName, rollNum, departmentNum, firstName1, lastName1, rollNum1, departmentNum1]

Il ne nous reste plus qu'à parcourir le tableau résultant ( arr ) jusqu'au milieu ( arr.length / 2 ) et mappez-le en utilisant Collectors.toMap


2 commentaires

Oui, ils le font. Juste que je trouve toujours la solution par sprinter beaucoup plus simple.


@nullpointer ouais, la solution du sprinter est beaucoup plus simple. J'ai dû lire ce code de manipulation de chaîne plusieurs fois pour comprendre qu'il est censé être une variante inefficace de String [] arr = Arrays.stream (currentString.split ("=")) .flatMap (s -> Arrays .stream (s.split ("-"))) .toArray (String [] :: new); , mais même pas correct, car il insère un espace à la première valeur. Sans parler de ce qui se passe lors de son utilisation avec des valeurs d'entrée différentes contenant un '[' , ']' , ou ','



3
votes

Comme indiqué dans cette réponse , une opération basée sur un tableau simple peut être beaucoup plus simple ici.

Mais si vous insister sur une solution Stream, cela peut ressembler à

Map<String,String> mapVal= Stream.of(currentString)
    .map(s0 -> Arrays.stream(s0.split("\\s*=\\s*", 2))
        .map(s1 -> s1.split("-")).toArray(String[][]::new))
    .flatMap(a -> IntStream.range(0, a[0].length)
        .mapToObj(i -> new String[]{ a[0][i], i < a[1].length? a[1][i]: "" }))
    .collect(Collectors.toMap(a -> a[0], a -> a[1]));


2 commentaires

Honnêtement, j'ai laissé cela comme une tâche pour déterminer comment pourrais-je convertir cette solution en flux, et maintenant que j'ai jeté un coup d'œil à cela, j'en ai une autre pour mieux comprendre cela et voir à quel point cela va avec une approche plus générique. . Bien sûr, je pourrais voir Stream.of ici aussi, mais en pensant principalement au split et aux pings de map .


@nullpointer bien, prenez la solution de sprinter, refactorisez les deux expressions currentString.split ("=") en une valeur locale déclarée avant cela, puis convertissez toutes ces étapes en une opération Stream. Puisqu'un Stream ne peut pas contenir une paire de deux éléments, vous devez utiliser un tableau pour contenir des clés et des valeurs (bidimensionnelles car ces deux variables ont déjà un type de tableau) . Après cette conversion, le refactoriser deux utilise une opération de flux pour la création de String [] [] , afin de ne plus avoir deux opérations split ('-') . Ensuite, vous êtes à ma réponse…



0
votes

Une autre manière serait comme ceci:

IntStream.range(0, map.get(true).size())
            .boxed()
            .collect(toMap(i -> map.get(false).get(i), i -> map.get(true).get(i)));

le résultat de cette étape est:

{
  false=[firstName, lastName, rollNum, departmentNum],

  true=[firstName1, lastName1, rollNum1, departmentNum1]
}

puis convertissez le résultat précédent en résultat final:

Pattern pattern = Pattern.compile("\\s*=\\s*");
int index = currentString.indexOf("=");
Map<Boolean, List<String>> map = pattern
            .splitAsStream(currentString.trim())
            .flatMap(s -> Stream.of(s.split("-")))
            .collect(partitioningBy(s -> currentString.indexOf(s) > index));


0 commentaires

0
votes
public static Map<String, String> toMap(String str) {
    String[] arr = str.split("[-=]");
    Map<String, String> map = new LinkedHashMap<>();

    for (int i = 0, j = arr.length / 2; j < arr.length; i++, j++)
        map.put(arr[i], arr[j]);

    return map;
}

2 commentaires

à la place j = 4; utilisez arr.length / 2;


Ce n'est pas important. J'aime ma solution, car pas besoin de faire arr.length / 2 4 fois