_CompletableFuture<Stream<String>>
_からの結果のストリームで複数の反復を許可するには、次のいずれかの方法を検討しています。
結果のフューチャーを_CompletableFuture<List<String>>
_に変換します:teams.thenApply(st -> st.collect(toList()))
結果のフューチャーをキャッシュ付き_Flux<String>
_に変換します:Flux.fromStream(teams::join).cache();
_Flux<T>
_は、プロジェクトリアクタ内の_Publisher<T>
_の実装です。
使用例:
League
オブジェクトに_Stream<String>
_(football-data RESTful APIに基づく)を提供するデータソースから、プレミアリーグチーム名(_Standing[]
_など)のシーケンスを取得したい例: http://api.football-data.org/v1/soccerseasons/445/leagueTable )。 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));
_
結果のストリームを再利用するには、2つのオプションがあります。
_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>>
_:
List<String>
_は継続的に収集され、将来の結果に進む必要がある場合は、おそらくすでに完了しています。List<T>
_でこれらのアイテムを収集する必要はありません。_Flux<String>
_:
.cache()
を省略して次のレイヤーに転送できます。これにより、リアクティブAPIを利用できます。ウェブフラックス反応コントローラー、例えば@GetMapping(produces =MediaType.TEXT_EVENT_STREAM) public Flux<String> getTeams() {…}
Flux<T>
_を再利用する場合は、キャッシュ可能な_Flux<T>
_(….cache()
)でラップする必要があります。これにより、最初のトラバーサルにオーバーヘッドが追加されます。結果のアイテムを内部キャッシュに保存します。_ CompletableFuture<Stream<String>> teams = ...;
Flux<String> teamsFlux = Mono.fromFuture(teams).flatMapMany(stream -> Flux.fromStream(stream));
_
Flux.fromStream(teams::join)
は、別のスレッドで実行されているCompletableFutureから結果をフェッチするスレッドを保持しているため、コードの匂いです。
リーグテーブルをダウンロードし、チーム名がこのテーブルから抽出されると、これらのアイテムを反復処理するためのバックプレッシャー対応ストリームが必要かどうかはわかりません。ストリームを標準リスト(または配列)に変換するだけで十分であり、おそらくパフォーマンスが向上するはずです。
例えば:
String[] teamNames = teams.join().toArray(String[]::new);