在Java中使用流拆分单词列表

在Java中使用流拆分单词列表,java,regex,string,java-8,java-stream,Java,Regex,String,Java 8,Java Stream,我有一个方法,它需要许多列表,其中包含一行的书籍。我将它们合并到一个流中,然后对它们进行迭代,以拆分所有非字母的\\P{L} 有没有一种方法可以避免for-each循环并在流中处理它 private List<String> getWordList(List<String>... lists) { List<String> wordList = new ArrayList<>(); Stream<String

我有一个方法,它需要许多列表,其中包含一行的书籍。我将它们合并到一个流中,然后对它们进行迭代,以拆分所有非字母的
\\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;
}
私有列表getWordList(列表…列表){
List wordList=new ArrayList();
Stream combinedStream=Stream.of(列表)
.flatMap(集合::流);
List combinedLists=combinedStream.collect(Collectors.toList());
for(字符串行:组合列表){
addAll(Arrays.asList(line.split(\\P{L}));
}
返回词表;
}

拥有流,您只需进一步“
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());
}
私有列表getWordList(列表…列表){
返回流.of(列表)
.flatMap(集合::流)
.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());
}
私有列表getWordList(列表…列表){
返回流.of(列表)
.flatMap(集合::流)
.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>
}
私有列表getWordList(列表…列表){
返回Stream.of(列表)//Stream
.flatMap(集合::流)//流
.flatMap(Pattern.compile(\\P{L}”)::splitAsStream)//流
.collect(toList());//列表
}
正如霍尔格所强调的,
.flatMap(Pattern.compile(\\p{L}”)::splitAsStream)


应该优先于
.flatMap(s->Arrays.stream(s.split(\\P{L}”)
,以避免为流的每个元素执行数组分配和模式编译。

str
在这里不是字符串,而是
列表。因此,
List.split()
无法编译。您错过了一个中间操作:如前所述,建议使用
.flatMap(Pattern.compile(\\P{L}”)::splitAsStream)
,这样可以避免为每个流元素重新编译模式,并且不会填充可能较大的中间数组。@Holger非常感谢您的参考。我还没有在Java8中看到这个。但我不太喜欢这种情况下的方法引用
(Pattern.splitAsStream(String)
至少对我来说并不常见),但根据你在另一篇文章中的评论,它是必需的,我明白了。我们也可以在流之外编译模式,但也不可怕。您还可以将模式移动到常量,如
static final pattern NON_LETTER_CHARS=pattern.compile(\\P{L}”)
然后使用
.flatMap(非字母字符::splitAsStream)
.flatMap(s->NON字母字符.splitAsStream))
。最后,在使用
s.split(\\P{L}”)
时,您还必须了解regex引擎。事实上,这就是我在注释编辑中引用的,对不起。这是一种方式,但也不可怕。