【问题标题】:Split list of words using streams in Java在 Java 中使用流拆分单词列表
【发布时间】:2019-07-24 22:12:49
【问题描述】:

我有这种方法,它需要一些列表,其中包含书籍行。我将它们组合成一个流,然后遍历它们以拆分所有非字母的\\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;
}

【问题讨论】:

    标签: java regex string java-8 java-stream


    【解决方案1】:

    有了流,你可以简单地“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());
    }
    

    【讨论】:

      【解决方案2】:

      你不需要引入那么多变量:

      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>
      }
      

      正如 Holger 强调的那样,.flatMap(Pattern.compile("\\P{L}")::splitAsStream)
      应该优先于.flatMap(s -&gt; Arrays.stream(s.split("\\P{L}"))),以节省为流的每个元素执行的数组分配和模式编译。

      【讨论】:

      • 正如in this answer 解释的那样,建议使用.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 -&gt; NON_LETTER_CHARS.splitAsStream(s))。最后,在使用s.split("\\P{L}")时,你还必须了解正则表达式引擎。
      • 确实是我在评论编辑中引用的,对不起。这是一种方式,但也不可怕。
      【解决方案3】:

      您可以将所有列表和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());
      }
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多