У меня есть этот метод, который принимает несколько списков, содержащих строки книг. Я расчесываю их в поток, чтобы затем перебрать их, чтобы разделить на все небуквенные \\P{L}.
Есть ли способ избежать цикла for-each и обработать его в потоке?
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;
}




Имея стрим можно просто "flatMap" дальше и вернуть результат:
return combinedStream
.flatMap(str -> Arrays.stream(str.split("\\P{L}")))
.collect(Collectors.toList());
Если выразиться вообще:
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());
}
Вы можете объединить весь список и flatMap для результата
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());
}
Вам не нужно вводить так много переменных:
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>
}
Как подчеркнул Хольгер, .flatMap(Pattern.compile("\\P{L}")::splitAsStream)
следует предпочесть .flatMap(s -> Arrays.stream(s.split("\\P{L}"))), чтобы сэкономить выделение массива и компиляцию шаблона, выполняемую для каждого элемента потока.
Как поясняется в этом ответе, рекомендуется использовать .flatMap(Pattern.compile("\\P{L}") ::splitAsStream), чтобы избежать повторной компиляции шаблона для каждого элемента потока и не заполнять потенциально большой промежуточный массив.
@Holger Большое спасибо за эту ссылку. Я еще не видел этого из Java 8. Но мне не очень нравится ссылка на метод в этом случае (Pattern.splitAsStream(String), по крайней мере, для меня не используется), но, согласно вашему комментарию в другом посте, это требуется, и я его получаю. Мы также можем скомпилировать шаблон вне потока, но это тоже не страшно.
Ну, вы также можете переместить шаблон в константу, например static final Pattern NON_LETTER_CHARS = Pattern.compile("\\P{L}");, а затем использовать либо .flatMap(NON_LETTER_CHARS::splitAsStream), либо .flatMap(s -> NON_LETTER_CHARS.splitAsStream(s)). В конце концов, вы также должны знать о механизме регулярных выражений при использовании s.split("\\P{L}").
Действительно, это то, на что я ссылался в своем комментарии, извините. Это способ, но это не страшно.
strздесь не строка, аList. Так чтоList.split()не может скомпилироваться. Вы пропустили промежуточную операцию: stackoverflow.com/a/54969149/270371