转换CompletableFuture <stream <t>&gt;是否正确?发布者<t>?

时间:2018-03-09 22:52:22

标签: java asynchronous rx-java reactive-programming project-reactor

要允许对CompletableFuture<Stream<String>>生成的流进行多次迭代,我正在考虑采用以下方法之一:

  1. 将生成的未来转换为CompletableFuture<List<String>>至:teams.thenApply(st -> st.collect(toList()))

  2. 将生成的未来转换为Flux<String>缓存:Flux.fromStream(teams::join).cache();

  3. Flux<T>是项目反应堆中Publisher<T>的实施。

    使用案例

    我想从数据源获得一个包含英超联赛球队名称的序列(例如Stream<String>),该数据源提供League对象Standing[](基于足球数据) RESTful API,例如http://api.football-data.org/v1/soccerseasons/445/leagueTable)。使用AsyncHttpClientGson我们有:

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

    要重新使用生成的流,我有两个选择:

    1. CompletableFuture<List<String>> res = teams.thenApply(st -> st.collect(toList()))
    
    2. Flux<String> res = Flux.fromStream(teams::join).cache()
    

    Flux<T>不那么冗长,并提供我所需要的一切。然而,在这种情况下使用它是否正确?

    或者我应该使用CompletableFuture<List<String>>代替?或者还有其他更好的选择吗?

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

    CompletableFuture<List<String>>

    • [PROS] List<String>将继续收集,当我们需要继续处理未来的结果时,可能已经完成。
    • [CONS]宣言冗长。
    • [CONS]如果我们只想使用一次,那么我们就不需要在List<T>中收集这些项目了。

    Flux<String>

    • [PROS]声明简洁
    • [PROS]如果我们只想使用一次,那么我们可以省略.cache()并将其转发到下一层,这可以利用反应API,例如卷材反应控制器,例如, @GetMapping(produces =MediaType.TEXT_EVENT_STREAM) public Flux<String> getTeams() {…}
    • [CONS]如果我们想重用那个Flux<T>,我们必须将它包装在可缓存的Flux<T>….cache())中,这反过来会增加第一次遍历的开销,因为它必须将结果项存储在内部缓存中。

2 个答案:

答案 0 :(得分:6)

    CompletableFuture<Stream<String>> teams = ...;
    Flux<String> teamsFlux = Mono.fromFuture(teams).flatMapMany(stream -> Flux.fromStream(stream));
编辑:

Flux.fromStream(teams::join)是一种代码异味,因为它持有一个线程来从运行在另一个线程上的CompletableFuture中获取结果。

答案 1 :(得分:3)

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

例如:

String[] teamNames = teams.join().toArray(String[]::new);