如何将String拆分为字符串流?

sla*_*dan 49 java regex split java-stream

将String拆分为Stream 的最佳方法是什么?

我看到了这些变化:

  1. Arrays.stream("b,l,a".split(","))
  2. Stream.of("b,l,a".split(","))
  3. Pattern.compile(",").splitAsStream("b,l,a")

我的优先事项是:

  • 稳健性
  • 可读性
  • 性能

一个完整的,可编译的例子:

import java.util.Arrays;
import java.util.regex.Pattern;
import java.util.stream.Stream;

public class HelloWorld {

    public static void main(String[] args) {
        stream1().forEach(System.out::println);
        stream2().forEach(System.out::println);
        stream3().forEach(System.out::println);
    }

    private static Stream<String> stream1() {
        return Arrays.stream("b,l,a".split(","));
    }

    private static Stream<String> stream2() {
        return Stream.of("b,l,a".split(","));
    }

    private static Stream<String> stream3() {
        return Pattern.compile(",").splitAsStream("b,l,a");
    }

}
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 67

好吧,既然String.split返回一个数组,我总是推荐String.split作为数组流的规范习语.String[]是一个可变参数这恰好接受的阵列,由于该可变参数的方法是通过阵列实现,并有当可变参数被引入Java和现有方法改装到可接受可变参数兼容性问题的事实方法.

Arrays.stream具有直接流式传输而不是创建中间阵列的优势.因此,对于大量子字符串,这可以具有性能优势.另一方面,如果分隔符是微不足道的,即单个文字字符,则Stream.of实现将通过快速路径而不是使用正则表达式引擎.所以在这种情况下,答案并非无足轻重.

如果流发生在另一个流内部,例如Stream.of,优点是必须仅分析模式一次,而不是分析外部流的每个字符串.

  • @Roland:这是`expression :: name`形式的方法引用的属性,表达式将被计算并且由创建的函数实例捕获结果.使用`Pattern.compile(pattern):: splitAsStream`,表达式为`Pattern.compile(pattern)`.这与根本不同,例如`(string) - > Pattern.compile(pattern).splitAsStream(string)`会重新评估每个函数评估的模式.见[这里](/sf/ask/2618917451/)和[这里](/sf/answers/1961800221/)...... (15认同)
  • @Benj 的问题是它甚至调用了 `subSequence(...).toString()`,所以使用不同的 `CharSequence` 实现(即非复制 [`CharBuffer.wrap(string)`](https:// docs.oracle.com/javase/8/docs/api/?java/nio/CharBuffer.html)) 只会将复制推迟到后续的 `toString()` 调用。但是对于标记化,无论如何您都希望使用 Java 9 的 `Matcher.results()` 或 `Scanner.findAll(...)`,因此请考虑 [this answer](/sf/answers/2623751021/) 的向后移植/2711488)。由于`MatchResult` 提供了`start()` 和`end()`,您可以在其上构建无复制操作。 (2认同)
  • @Benj 您也可以考虑 [this answer](/sf/answers/3372081331/) 的后半部分,其中包含标记化的代码示例,该示例仅为每个唯一标记创建一个 `String` 实例,这在解析具有大量常见关键字的内容时显着减少了时间和内存占用。 (2认同)
  • 似乎番石榴的 [Splitter](https://google.github.io/guava/releases/20.0/api/docs/com/google/common/base/Splitter.html) 有一种有趣的方式来做到这一点,我偶然发现这或多或少是随机的。 (2认同)