J'ai cette méthode qui prend un certain nombre de listes, qui contiennent des lignes de livres. Je les combine en un flux pour ensuite les parcourir pour les diviser sur tous les \\ P {L}
de non-lettre.
Existe-t-il un moyen d'éviter la boucle for-each et de la traiter dans un flux?
private List<String> getWordList(List<String>... lists) { List<String> wordList = new ArrayList<>(); Stream<String> combinedStream = Stream.of(lists) .flatMap(Collection::stream); List<String> combinedLists = combinedStream.collect(Collectors.toList()); for (String line: combinedLists) { wordList.addAll(Arrays.asList(line.split("\\P{L}"))); } return wordList; }
3 Réponses :
Ayant stream, vous pouvez simplement " flatMap
" plus loin et renvoyer le résultat:
private List<String> getWordList(List<String>... lists) { return Stream.of(lists) .flatMap(Collection::stream) .flatMap(str -> Arrays.stream(str.split("\\P{L}"))) .collect(Collectors.toList()); }
Pour tout dire:
return combinedStream .flatMap(str -> Arrays.stream(str.split("\\P{L}"))) .collect(Collectors.toList());
Vous pouvez combiner toute la liste et flatMap
pour le résultat
private List<String> getWordList(List<String>... lists) { return Stream.of(lists) .flatMap(Collection::stream) .flatMap(str -> Arrays.stream(str.split("\\P{L}"))) .collect(Collectors.toList()); }
str
n'est pas ici une chaîne mais une liste
. Donc List.split ()
ne peut pas compiler. Vous manquez une opération intermédiaire: stackoverflow.com/a/54969149/270371
Vous n'avez pas besoin d'introduire autant de variables:
private List<String> getWordList(List<String>... lists) { return Stream.of(lists) // Stream<Stream<String>> .flatMap(Collection::stream) // Stream<String> .flatMap(Pattern.compile("\\P{L}")::splitAsStream) //Stream<String> .collect(toList()); // List<String> }
Comme souligné par Holger, .flatMap (Pattern.compile ("\\ P {L}"): : splitAsStream)
devrait être privilégié par rapport à .flatMap (s -> Arrays.stream (s.split ("\\ P {L}")))
pour épargner l'allocation de tableau et la compilation de modèles effectuées pour chaque élément du flux .
Comme expliqué dans cette réponse , il est recommandé d'utiliser .flatMap (Pattern.compile ("\\ P {L } ") :: splitAsStream)
, cela évite de recompiler le modèle pour chaque élément de flux et ne remplit pas un tableau intermédiaire potentiellement grand.
@Holger Merci beaucoup pour cette référence. Je n'ai pas encore vu celui-ci de Java 8. Mais je n'aime pas beaucoup la référence de méthode dans ce cas (Pattern.splitAsStream (String)
n'est pas courant à utiliser pour moi au moins ) mais d'après votre commentaire dans l'autre post, il est obligatoire et je comprends. On pourrait aussi compiler le pattern en dehors du stream mais enfin pas terrible non plus.
Eh bien, vous pouvez également déplacer le modèle vers une constante comme static final Pattern NON_LETTER_CHARS = Pattern.compile ("\\ P {L}");
puis utiliser soit .flatMap (NON_LETTER_CHARS: : splitAsStream)
ou .flatMap (s -> NON_LETTER_CHARS.splitAsStream (s))
. En fin de compte, vous devez également connaître le moteur de regex lorsque vous utilisez s.split ("\\ P {L}")
.
En effet c'est ce que j'ai référencé dans mon commentaire edit, désolé. C'est un moyen mais ce n'est pas terrible non plus.