如何将StreamEx解包为“普通的Java Stream”?

3

StreamEx是一个功能强大的库,但在某些时候我不再需要它的超级能力。

我该如何摆脱StreamEx内部的开销?这会带来问题吗?

例如:

public void process(Path path){
    StreamEx.of(Files.lines(path))
        .groupRuns(...)
        //See below 
        .unwrap()
        //
        .map(...)
        .forEach(...)
}

7
在我看来,StreamEx 就是一个 Stream,标准操作都被委托给了 Stream,因此实际上没有任何额外的开销(除了多创建一个对象之外)。我会让它的作者给出一个恰当的回答 :)。 - Tunaki
1个回答

13

没有公共的API方法可以“取消包装”StreamEx流。这是有意为之的。一般来说,StreamEx类与原始的Stream API兼容,因此如果你需要将StreamEx传递给接受简单Stream的某些代码,你可以毫无顾虑地这样做。

使用StreamEx的开销通常非常低:每个流步骤仅有一到几次额外的调用(其中一些可能会被JIT编译器消除)。这个开销(如果没有被JIT消除)只会在流创建期间出现,而不是在评估期间出现,因此它不取决于流中元素的数量。当终端操作发生时,处理将交给原始流,在您的例子中,在mapforEach评估期间,没有任何StreamEx库代码将运行。

如果您创建许多简短的简单流,则StreamEx的开销可能会相对较高。例如,如果您在flatMap内部创建StreamEx实例。因此,在这种情况下,如果性能很重要并且您不需要嵌套的Stream的特定StreamEx操作,那么可能最好避免在flatMap内使用StreamEx。不过,根据我的测试,只有在非常人为的情况下,差异才会变得明显(例如,超过5%)。

请注意,一些StreamEx操作与Stream API等效操作相比进行了优化。例如,StreamEx.toList()通常比Stream.collect(Collectors.toList())快。像StreamEx.of(persons).map(Person::getName).toList()这样的简单创建-映射-收集操作,可以比persons.stream().map(Person::getName).collect(Collectors.toList())快几倍。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接