如何将 StreamEx 解包为 "Plain Old Java Stream"?

How to unwrap StreamEx to a "Plain Old Java Stream"?

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

我怎样才能摆脱 StreamEx 内部开销?这会带来问题吗?

例如

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

"unwrap" StreamEx 流没有 public API 方法。这是故意的。通常 StreamEx class 与原始 Stream API 兼容,因此如果您需要将 StreamEx 传递给某些接受简单 Stream 的代码,你可以毫无恐惧地做到这一点。

使用 StreamEx 的开销通常很低:每个流步骤只有一个或几个额外的调用(其中一些可以被 JIT 编译器消除)。此开销(如果未被 JIT 消除)仅出现在流创建期间,而不出现在评估期间,因此它不依赖于流中元素的数量。当终端操作发生时,处理被移交给原始流,因此在 mapforEach 评估期间的示例中,没有 StreamEx 库代码将是 运行.

如果您创建许多简单的短流,StreamEx 开销可能会有些显着。例如,如果您在 flatMap 中创建 StreamEx 实例。因此,在这种情况下,如果性能很重要并且您不需要对嵌套 Stream 进行特定的 StreamEx 操作,那么避免 flatMap 内部的 StreamEx 可能是个好主意。尽管根据我的测试,差异仅在非常人为的情况下才会变得显着(比如超过 5%)。

请注意,与 Stream API 等价物相比,一些 StreamEx 操作已经过优化。例如,StreamEx.toList() 通常比 Stream.collect(Collectors.toList()) 快。与 persons.stream().map(Person::getName).collect(Collectors.toList()).

相比,像 StreamEx.of(persons).map(Person::getName).toList() 这样简单的 create-map-collect 操作可以快几倍