web-dev-qa-db-ja.com

CompletableFuture <Stream <T >>をPublisher <T>に変換することは正しいですか?

_CompletableFuture<Stream<String>>_からの結果のストリームで複数の反復を許可するには、次のいずれかの方法を検討しています。

  1. 結果のフューチャーを_CompletableFuture<List<String>>_に変換します:teams.thenApply(st -> st.collect(toList()))

  2. 結果のフューチャーをキャッシュ付き_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 )。 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));
_

結果のストリームを再利用するには、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>>_:

  • [PROS] _List<String>_は継続的に収集され、将来の結果に進む必要がある場合は、おそらくすでに完了しています。
  • [短所]宣言の冗長性。
  • [短所]一度だけ使用する場合は、_List<T>_でこれらのアイテムを収集する必要はありません。

_Flux<String>_:

  • [長所]宣言の簡潔さ
  • [PROS]一度だけ使用する場合は、.cache()を省略して次のレイヤーに転送できます。これにより、リアクティブAPIを利用できます。ウェブフラックス反応コントローラー、例えば@GetMapping(produces =MediaType.TEXT_EVENT_STREAM) public Flux<String> getTeams() {…}
  • [短所]その_Flux<T>_を再利用する場合は、キャッシュ可能な_Flux<T>_(….cache())でラップする必要があります。これにより、最初のトラバーサルにオーバーヘッドが追加されます。結果のアイテムを内部キャッシュに保存します。
21
Miguel Gamboa
_    CompletableFuture<Stream<String>> teams = ...;
    Flux<String> teamsFlux = Mono.fromFuture(teams).flatMapMany(stream -> Flux.fromStream(stream));
_

Flux.fromStream(teams::join)は、別のスレッドで実行されているCompletableFutureから結果をフェッチするスレッドを保持しているため、コードの匂いです。

7
youhans

リーグテーブルをダウンロードし、チーム名がこのテーブルから抽出されると、これらのアイテムを反復処理するためのバックプレッシャー対応ストリームが必要かどうかはわかりません。ストリームを標準リスト(または配列)に変換するだけで十分であり、おそらくパフォーマンスが向上するはずです。

例えば:

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