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]声明的简洁性
- [优点]如果我们只想使用一次,那么我们可以省略
并将其转发到下一层,这可以利用反应式API,例如web flux反应式控制器,例如.cache()
@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));