1

私はJava 8で並行性とラムダを学ぼうとしています。しかし、私のコードはマップ内のラムダブロックに入っていません。マップ内のラムダが実行されていないのはなぜですか?

List<Book> bookList = new ArrayList<Book>(); 
    isbnList 
    .stream() 
    .map(isbn -> (CompletableFuture.supplyAsync(() -> { 
     try { 
      List<String> pageContents = getUrlContents(webLink + isbn); 
      return new Book(
       parseBookTitle(pageContents), 
       isbn, 
       parseRank(pageContents) 
      ); 
     } catch (IOException ex) { 
      return null; 
     } 
    })).thenApply(a -> bookList.add(a)) 
    ); 

デバッグ中に、コードは.map行で終了し、空のbookListを取得しています。シーケンシャルコードで正しい結果が得られます。

答えて

7

ストリームパイプラインは、怠惰です。 端末操作がなければ、ストリームパイプラインは実行されません。 Stream.map中間操作であるため、パイプライン実行をトリガーしません。

今、あなたは、実行するあなたのパイプラインのためのあなたの作成したCompletableFutureインスタンスに参加するためのラムダ式cf -> cf.join()forEachステップを追加し、完了するために、あなたの非同期先物ごとに待つことができます。しかし、このようにすると、非同期先物を使用するという全目的を敗北させることになります。なぜなら、それらを順番に提出し、次のものを提出する前にそれぞれの完了を待っているからです。

はいっそのこと、あなたは、パラレルストリームにあなたのストリームに変換する直接CompletableFuture.supplyAsync一部を除去し、余分な混乱せずに同様の効果を得るためcollectを集めることによって、あなたの非同期ラムダ本体とmapを使用することができます。

List<Book> bookList = isbnList.parallelStream() 
    .map(isbn -> { 
     try { 
      List<String> pageContents = getUrlContents(webLink + isbn); 
      return new Book(
       parseBookTitle(pageContents), 
       isbn, 
       parseRank(pageContents) 
      ); 
     } catch (IOException ex) { 
      throw new RuntimeException(ex); 
     } 
    }).collect(Collectors.toList()); 

追加情報:ストリームAPI javadocのStream operations and pipelines

+0

マップをforEachに置き換えましたが、制御はラムダブロック内にはありません。提案してください。 – Manvi

+2

非同期タスクを共通のフォークジョインプールに送信していますが、結果を待っているわけではありません。タスクが完了したことを確認する必要があります。マップを使用することに戻りますが、forEachで非同期先物取引に参加してください。私は私の答えを更新します。私はそれに応じて私の答えを更新します。 –

+0

ありがとうナンドール。出来た。 – Manvi

関連する問題