I am having this method that takes a number of lists, which contain lines of books. I am combing them to a stream to then iterate over them to split on all non-letter's \\P{L}
.
Is there a way to avoid the for-each loop and process this within a stream?
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;
}
Having stream, you can simply "flatMap
" further and return the result:
return combinedStream
.flatMap(str -> Arrays.stream(str.split("\\P{L}")))
.collect(Collectors.toList());
To put it altogether:
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());
}
You don't need to introduce so many 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>
}
As underlined by Holger, .flatMap(Pattern.compile("\\P{L}")::splitAsStream)
should be favored over .flatMap(s -> Arrays.stream(s.split("\\P{L}")))
to spare array allocation and pattern compilation performed for each element of the stream.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With