1

Ich versuche, Nebenläufigkeit und Lambdas in Java 8 zu lernen. Aber mein Code ist nicht in Lambda-Block in Karte eingeben.Warum Lambda innerhalb der Karte nicht läuft?

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

Während des Debuggens wird der Code bei .map line beendet und ich bekomme eine leere Buchliste. Sequenzieller Code für dasselbe gibt mir das richtige Ergebnis.

Antwort

7

Eine Stream-Pipeline ist faul. Ohne eine Terminaloperation wird Ihre Stream-Pipeline nicht einmal ausgeführt. Stream.map ist eine Zwischenoperation, so dass es keine Pipelineausführung auslöst.

Nun könnte man einen forEach Schritt mit dem Lambda-Ausdruck cf -> cf.join() zum Verbinden auf Ihren erstellt CompletableFuture Instanzen für Ihre Pipeline hinzufügen, für jede Ihres Asynchron-Futures zu vervollständigen ausgeführt und warten wird. Wenn Sie so vorgehen, wird der ganze Zweck der Verwendung von asynchronen Futures zunichte gemacht, weil Sie sie sequentiell abliefern und auf den Abschluss jedes einzelnen warten, bevor Sie den nächsten einreichen.

Noch besser wäre es, könnten Sie Ihren Stream zu einem parallel Strom zu konvertieren, verwenden map mit Ihrem Körper Asynchron-Lambda direkt durch den CompletableFuture.supplyAsync Teil zu entfernen und mit collect für einen ähnlichen Effekt ohne die zusätzliche Unordnung zu sammeln.

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

Weiterführende Literatur: Stream operations and pipelines im Stream API Javadoc.

+0

Ersetzt Karte mit ForEach aber noch Kontrolle geht nicht in Lambda-Block. Bitte vorschlagen. – Manvi

+2

Sie senden asynchrone Aufgaben an den gemeinsamen Fork-Join-Pool, aber Sie warten nicht auf die Ergebnisse. Sie müssen sicherstellen, dass Ihre Aufgaben abgeschlossen sind. Gehen Sie zurück zur Karte, aber verbinden Sie sich für Ihre asynchronen Futures in einem forEach. Ich werde meine Antwort aktualisieren. Ich werde meine Antwort entsprechend aktualisieren. –

+0

Danke Nándor. Es funktionierte. – Manvi