java 如何将一个字符串拆分成一个字符串流?

bakd9h0s  于 2023-05-15  发布在  Java
关注(0)|答案(3)|浏览(208)

将String拆分为Stream的最好方法是什么?
我看到了这些变化:

  1. Arrays.stream("b,l,a".split(","))
  2. Stream.of("b,l,a".split(","))
  3. Pattern.compile(",").splitAsStream("b,l,a")
    我的首要任务是:
  • 稳健性
  • 可读性
  • 产品展示

一个完整的、可编译的example

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

}
bqf10yzr

bqf10yzr1#

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是一个 varargs 方法,它恰好接受一个数组,这是因为varargs方法是通过数组实现的,并且在将varargs引入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);

如果流传输发生在另一流内部,例如存在这样的优点,即模式只需要被分析一次,而不是针对外部流的每个串。

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

这是形式为expression::name的方法引用的属性,它将在创建函数接口的示例时计算表达式并捕获结果,如What is the equivalent lambda expression for System.out::printlnjava.lang.NullPointerException is thrown using a method-reference but not a lambda expression中所述

htzpubme

htzpubme2#

稳健性
我看不出这三种方法的鲁棒性有什么不同。
可读性
我不知道有任何可信的科学研究涉及到有经验的Java程序员,所以可读性是一个观点问题。即便如此,你也永远不知道某人给出的意见是否客观地区分了实际的可读性,他们所学到的关于可读性的知识,以及他们自己的个人品味。
所以我会让你自己对可读性做出判断。我注意到你认为这是一个高优先级。
FWIW,在这件事上唯一有意见的人就是你和你的团队。
产品展示
我认为,解决这个问题的答案是仔细衡量这三种选择。Holger根据他对Java的一些版本的研究提供了一个分析。但是:
1.他无法得出一个明确的结论,哪一个是最快的。
1.严格地说,他的分析只适用于他所研究的Java版本。(他的分析的某些方面 * 可能 * 在(比如)Android Java或未来的Oracle / OpenJDK版本上有所不同。
1.相对性能可能取决于拆分的字符串的长度、字段的数量以及分隔符正则表达式的复杂性。
1.在真实的的应用程序中,相对性能还可能取决于您对Stream对象所做的操作、您选择的垃圾收集器(因为不同的版本显然会生成不同数量的垃圾)以及其他问题。
因此,如果您(或其他任何人)真的关心性能,您应该编写一个微基准测试并在您的生产平台上运行它。然后做一些特定于应用程序的基准测试。您应该考虑寻找不涉及流的解决方案。

v1uwarro

v1uwarro3#

关于(1)和(2),应该没有太大的区别,因为你的代码几乎是一样的。
关于(3),这在内存方面会更有效(不一定是CPU),但在我看来,有点难以阅读。

相关问题