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

时间:2016-12-02 12:58:32

标签: java regex split java-stream

将字符串拆分为流的最佳方法是什么?

我看到了这些变化:

  1. Stream.of("b,l,a".split(","))
  2. Pattern.compile(",").splitAsStream("b,l,a")
  3. 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"); } }
  4. 我的优先事项是:

    • 鲁棒性
    • 可读性
    • 性能

    完整的,可编辑的example

    @IBOutlet weak var button: UIButton!
    

3 个答案:

答案 0 :(得分:53)

好吧,因为String.split返回一个数组,我总是建议Arrays.stream作为数组流的规范习惯用法。 Stream.of是一个 varargs 方法,恰好接受一个数组,因为varargs方法是通过数组实现的,当varargs被引入Java并且现有方法被改进时存在兼容性问题接受变量参数。

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

  

健壮性

我看不到这三种方法的鲁棒性。

  

可读性

我不了解涉及经验丰富的Java程序员的任何有关代码可读性的可靠科学研究,因此可读性只是一个见解。即使到那时,您也永远不会知道有人在发表意见时是否在实际可读性,他们对可读性的了解以及他们自己的个人品味之间做出客观区分。

因此,我将由您自己决定可读性...并指出您确实将其视为高度优先事项。

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

  

性能

我认为,答案是仔细基准化这三种选择。 Holger根据对Java某些版本的研究提供了分析。但是:

  1. 他无法就哪个最快的速度得出明确的结论。
  2. 严格来说,他的分析仅适用于他所研究的Java版本。 (他的分析的某些方面在(例如)Android Java上或将来的Oracle / OpenJDK版本上可能有所不同。)
  3. 相对性能可能取决于要拆分的字符串的长度,字段数以及分隔符regex的复杂性。
  4. 在实际的应用程序中,相对性能还可能取决于您对Stream对象的处理方式,选择的垃圾收集器(由于不同的版本显然会产生不同数量的垃圾)以及其他问题。 / li>

因此,如果您(或其他任何人)确实对性能感兴趣,则应编写一个微型基准并在生产平台上运行它。然后进行一些特定于应用程序的基准测试。而且,您应该考虑研究不涉及流的解决方案。