Java 转换一个完整的未来是否正确<;溪流<;T>&燃气轮机;给出版商<;T>;?

Java 转换一个完整的未来是否正确<;溪流<;T>&燃气轮机;给出版商<;T>;?,java,java-8,rx-java,project-reactor,completable-future,Java,Java 8,Rx Java,Project Reactor,Completable Future,为了允许对可完成未来的结果流进行多次迭代,我正在考虑以下方法之一: 通过:teams将生成的未来转换为CompletableFuture。然后应用(st->st.collect(toList()) 使用缓存将生成的未来转换为Flux:Flux.fromStream(teams::join.cache() Flux是项目反应堆中Publisher的实现 用例: 我想从一个数据源获取英超球队名称的序列(例如,流),该数据源提供了一个联赛对象,该对象具有一个站姿[](例如,基于足球数据RESTful

为了允许对
可完成未来的结果流进行多次迭代
,我正在考虑以下方法之一:

  • 通过:
    teams将生成的未来转换为
    CompletableFuture
    。然后应用(st->st.collect(toList())

  • 使用缓存将生成的未来转换为
    Flux
    Flux.fromStream(teams::join.cache()

  • Flux
    是项目反应堆中
    Publisher
    的实现

    用例:

    我想从一个数据源获取英超球队名称的序列(例如,
    ),该数据源提供了一个
    联赛
    对象,该对象具有一个
    站姿[]
    (例如,基于足球数据RESTful API)。使用
    AsyncHttpClient
    Gson
    我们有:

    CompletableFuture<Stream<String>> teams = asyncHttpClient
        .prepareGet("http://api.football-data.org/v1/soccerseasons/445/leagueTable")
        .execute()
        .toCompletableFuture()
        .thenApply(Response::getResponseBody)
        .thenApply(body -> gson.fromJson(body, League.class));
        .thenApply(l -> stream(l.standings).map(s -> s.teamName));
    
    CompletableFuture团队=asyncHttpClient
    .prepareGet(”http://api.football-data.org/v1/soccerseasons/445/leagueTable")
    .execute()
    .toCompletableFuture()
    .thenApply(响应::getResponseBody)
    .thenApply(body->gson.fromJson(body,League.class));
    .然后应用(l->stream(l.standings).map(s->s.teamName));
    
    要重新使用生成的流,我有两个选项:

    1. CompletableFuture<List<String>> res = teams.thenApply(st -> st.collect(toList()))
    
    2. Flux<String> res = Flux.fromStream(teams::join).cache()
    
    1。CompletableFuture res=团队。然后应用(st->st.collect(toList())
    2.Flux res=Flux.fromStream(teams::join).cache()
    
    Flux
    不那么冗长,提供了我所需要的一切。然而,在这种情况下使用它是否正确

    或者我应该使用
    CompletableFuture
    ?或者还有其他更好的选择吗

    更新了一些想法(2018-03-16)

    CompletableFuture

    • [PROS]将继续收集
      列表
      ,当我们需要继续处理未来的结果时,它可能已经完成
    • [反对]声明冗长
    • [CONS]如果我们只想使用一次,那么我们不需要在
      列表中收集这些项目
    通量

    • [PROS]声明的简洁性
    • [优点]如果我们只想使用一次,那么我们可以省略
      .cache()
      并将其转发到下一层,这可以利用反应式API,例如web flux反应式控制器,例如
      @GetMapping(products=MediaType.TEXT\u EVENT\u STREAM)public flux getTeams(){…}
    • [缺点]如果我们想重用
      通量
      ,我们必须将其包装在可缓存的
      通量
      …cache()
      )中,这反过来会增加第一次遍历的开销,因为它必须将结果项存储在内部缓存中

    一旦您下载了联赛表格,并且从该表格中提取了球队名称,我不确定您是否需要背压就绪流来迭代这些项目。流到标准列表(或数组)的转换应该足够好,并且应该有更好的性能,不是吗

    例如:

    String[] teamNames = teams.join().toArray(String[]::new);
    
    CompletableFuture团队=。。。;
    Flux teamsFlux=Mono.fromfourture(teams).flatMapMany(stream->Flux.fromStream(stream));
    
    编辑:
    Flux.fromStream(teams::join)
    是一种代码味道,因为它持有一个线程,从另一个线程上运行的CompletableFuture获取结果。

    我不确定开销。将项目收集到
    列表中也会导致额外的管理费用,不是吗?如果我们不总是重用生成的
    团队
    ,那么从
    供应商::流
    创建冷流可能会更有效,因为我们没有创建辅助
    列表
    对象。另一方面,如果我们确定要重用
    团队
    ,那么在
    列表中收集它可能比使用
    缓存()
    更好,因为后者会增加第一次遍历的开销。这些是我的疑问!!事实上,如果您的意图是读取一次流,那么您可以保留一条流;但是,如果您必须多次解析项目集合,我更愿意将项目流转换为项目数组,而不是使用背压就绪的冷流来迭代这些项目。不确定将异步管道转换为同步管道是我见过的最好的建议。“这反过来会在第一次遍历时增加开销“-可忽略不计,忽略此项。
    Flux
    是一个异步反应管道<代码>列表
    是一个
    列表
    。你需要什么?你在比较苹果和桔子。@Boristespider我不是在比较
    List
    Flux
    。我将
    CF
    Flux
    进行比较。这是
    Mono
    而不是
    Flux
    。很明显,两者是不同的。
    Mono
    CF
    相同。从
    CF
    转换到
    Mono
    没有任何优势。我认为它不包含调用
    fromStream(…)
    的线程。那是懒惰。我们只是将方法句柄传递给
    join
    ,而不是调用它。订阅之后,推送线程可能会保持在
    join()
    ,但只有在源
    CompletableFuture
    尚未完成的情况下。
        CompletableFuture<Stream<String>> teams = ...;
        Flux<String> teamsFlux = Mono.fromFuture(teams).flatMapMany(stream -> Flux.fromStream(stream));