9
votes

Comment diviser un flux de chaînes et générer une liste de tableaux de chaînes?

Je suis assez novice dans les streams, alors aidez-moi (et soyez gentil).

Ce que j'aimerais faire, c'est ce qui suit. J'ai un BufferedReader qui lit un fichier dans lequel chaque ligne ressemble à ceci: "a, b". Par exemple:

Exemple de fichier d'entrée

"a, b"

"d, e"

"f, g"

Je voudrais convertir ceci en une LinkedList>:

Exemple LinkedList >

[{"a", "b"}, {"c", "d"}, {"f", "g"} ]

Comment feriez-vous cela en utilisant une approche par flux?

Voici ce que j'ai essayé:

Incompatible types. Required List but 'collect' was inferred to R: no instance(s) of type variable(s) T exist so that List<T> conforms to List

Cela ne fonctionne pas . Mon IDE fournit les commentaires suivants:

List numbers = reader.lines().map(s -> s.split("[\\W]")).collect(Collectors.toList());

Cela montre ... J'essaie toujours de comprendre les flux.


4 commentaires

Commencez par ne pas utiliser de types bruts. Que doit contenir la liste? Si vous n'utilisiez pas de types rwa, votre code serait de type sécurisé et nous aurions ces informations critiques. Aussi, pourquoi utiliseriez-vous une LinkedList? Dans 99; 99% des cas, une ArrayList est un meilleur choix qu'une LinkedList.


@JBNizet: Voulez-vous dire utiliser LinkedList numbers = ... au lieu de List numbers = ... ? J'ai essayé cela aussi, cela n'a fait aucune différence.


[{"a", "b"}, {"c", "d"}, {"f", "g"}] quel est le type de {"a" , "b"} ? Map ? Map.Entry ?


Non. Je veux dire juste List au lieu de la liste brute. Vous voulez donc une liste de chaînes? Que doit contenir chaque chaîne de la liste? Lisez stackoverflow.com/questions/2770321/...


3 Réponses :


4
votes

Vous pouvez le faire comme ceci,

Path path = Paths.get("src/main/resources", "data.txt");
try (Stream<String> lines = Files.lines(path)) {
    List<String> strings = lines.flatMap(l -> Arrays.stream(l.split(","))).map(String::trim)
        .collect(Collectors.toCollection(LinkedList::new));
}

Lisez chaque ligne du fichier, puis divisez-le en utilisant le délimiteur. Après cela, coupez-le pour éliminer tous les caractères d'espace blanc restants. Enfin, récupérez-le dans un conteneur de résultats.


3 commentaires

Je préférerais cela à la réponse actuelle à mon humble avis. (+1)


@nullpointer Mais ce code produit une List au lieu d'une List> ...


@FedericoPeraltaSchaffner c'est la raison pour laquelle je préférerais cela. Peut-être que je trouve juste difficile de voir la liste d'un tableau comme un seul.



7
votes

Premièrement, je suggérerais d'éviter l'utilisation de types bruts et à la place, utilisez List comme type de récepteur.

List<String[]> numbers = reader.lines()
                               .map(s -> s.split(delimiter)) // substitute with your deilimeter
                               .collect(Collectors.toCollection(LinkedList::new));

Vous avez mentionné que vous vouliez une implémentation de LinkedList . vous devriez presque toujours privilégier ArrayList que toList renvoie par défaut actuellement bien qu'il ne soit pas garanti de persister ainsi, vous pouvez spécifier explicitement l'implémentation de la liste avec toCollection:

List<String[]> numbers = reader.lines()
                               .map(s -> s.split(delimiter)) // substitute with your deilimeter
                               .collect(Collectors.toCollection(ArrayList::new));

et de même pour LinkedList:

List<String[]> numbers = reader.lines()
                               .map(s -> s.split(delimiter)) // substitute with your deilimeter
                               .collect(Collectors.toList());

p>


1 commentaires

Merci qui a beaucoup aidé!



4
votes

En supposant que chaque ligne est un tuple de 2 éléments, vous pouvez les rassembler dans une liste de quelque chose qui ressemble à un tuple de 2 éléments. Notez que Java n'a pas de type natif pour les tuples (comme Scala ou python), vous devez donc choisir un moyen de représenter les éléments.

vous pouvez créer une liste d'entrées:

List<String> numbers = reader.lines()
                             .map(s -> s.split(","))
                             .map(a -> "{" + a[0] + "," + a[1] + "}"))
                             .collect(Collectors.toList());


2 commentaires

La première approche est une autre manière intéressante de stocker deux éléments associés +1. Cependant, la deuxième approche serait difficile à traiter avec vous si vous souhaitez ultérieurement accéder à chaque élément individuel et en faire quelque chose.


D'accord pour la seconde. Cela semble plus utilisable comme format de données. Pas facile de répondre intelligemment avec une exigence large :) EDIT: oh c'était dans le titre "et générer une liste de String-tableaux?" Ma faute :)