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

新手上路,请多包涵

将 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");
    }

}

原文由 slartidan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 798
2 个回答

Arrays.stream / String.split

由于 String.split 返回一个数组 String[] ,我总是推荐 Arrays.stream 作为流式传输数组的规范习惯用法。

 String input = "dog,cat,bird";
Stream<String> stream = Arrays.stream(input.split( "," ));
stream.forEach(System.out::println);

Stream.of / String.split

Stream.of 是一个 可变参数 方法,它恰好接受一个数组,因为可变参数方法是通过数组实现的,并且当可变参数被引入 Java 并且现有方法被改造为接受可变参数时存在兼容性问题。

 Stream<String> stream = Stream.of(input.split(","));     // works, but is non-idiomatic
Stream<String> stream = Stream.of("dog", "cat", "bird"); // intended use case

Pattern.splitAsStream

Pattern.compile(",").splitAsStream(string) 具有直接流式传输而不是创建中间数组的优势。因此对于大量的子字符串,这可以带来性能优势。另一方面,如果定界符是微不足道的,即单个文字字符, String.split 实现将通过快速路径而不是使用正则表达式引擎。所以在这种情况下,答案并不简单。

 Stream<String> stream = Pattern.compile(",").splitAsStream(input);

如果流式传输发生在另一个流中,例如 .flatMap(Pattern.compile(pattern) ::splitAsStream) 的优点是只需分析一次模式,而不是对外部流的每个字符串进行分析。

 Stream<String> stream = Stream.of("a,b", "c,d,e", "f", "g,h,i,j")
    .flatMap(Pattern.compile(",")::splitAsStream);

这是 expression::name 形式的方法引用的一个属性,它将在创建功能接口的实例时评估表达式并捕获结果,如 什么是 System.out 的等效 lambda 表达式中所述: :printlnjava.lang.NullPointerException 使用方法引用而不是 lambda 表达式抛出

原文由 Holger 发布,翻译遵循 CC BY-SA 4.0 许可协议

鲁棒性

我看不出这三种方法的稳健性有什么不同。

可读性

我不知道有任何关于代码可读性的可靠科学研究涉及有经验的 Java 程序员,所以可读性是一个见仁见智的问题。即便如此,您也永远不知道发表意见的人是否在客观区分实际可读性、他们所学的可读性以及他们自己的个人品味。

所以我会留给你对可读性做出自己的判断……注意到你确实认为这是一个高度优先的问题。

FWIW,唯一对此事有意见的人是你和你的团队。

表现

我认为这个问题的答案是仔细地对三种备选方案进行基准测试。 Holger 根据他对某些 Java 版本的研究提供了分析。但:

  1. 他无法得出一个明确的结论,即哪个速度最快。
  2. 严格来说,他的分析只适用于他看过的 Java 版本。 (他分析的某些方面 可能 在(比如)Android Java 或某些未来的 Oracle / OpenJDK 版本上有所不同。)
  3. 相对性能可能取决于被拆分的字符串的长度、字段的数量以及分隔符正则表达式的复杂性。
  4. 在实际应用程序中,相对性能还可能取决于您对 Stream 对象执行的操作、您选择的垃圾收集器(因为不同版本显然会产生不同数量的垃圾)以及其他问题。

因此,如果您(或其他任何人)真的很关心性能,您应该编写一个微基准测试并在您的生产平台上运行它。然后做一些特定于应用程序的基准测试。您应该考虑寻找不涉及流的解决方案。

原文由 Stephen C 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题