2016-11-21 22 views
1

我有點困惑,現在我,所以我也應該返回CompletableFuture<List<A>>CompletableFutures和過濾依據是內部

方法裏面的方法值是:

CompletableFuture<List<String>> toReturn = asyncCall().thenApply(....) 
.thenCompose(listOfStuff -> convertToList(listOfStuff.stream().map(
    key -> asyncCall2(key) 
     .thenApply(optionalValue -> optionalValue.orElse(null)) 
).collect(Collectors.toList())); 

convertToList()只需加入期貨CompletableFuture<List<ComputableFuture<A>>>轉換成CompletableFuture<List<A>>

基本上我的意圖是,以過濾從optionalValue.orElse(null)出現空值,而且它會很容易科爾之前做過濾器所有這一切都列在最後一行,但如果我在.collect之前使用它,它正在完成CompletableFutures

我懷疑在我的代碼中可以做很多重構。

編輯:

private<T> CompletableFuture<List<T>> convertToList(List<CompletableFuture<T>> toConvert) { 
    return CompletableFuture.allOf(toConvert.toArray(new CompletableFuture[toConvert.size()])) 
      .thenApply(v -> toConvert.stream() 
        .map(CompletableFuture::join) 
        .collect(Collectors.toList()) 
      ); 
} 
+0

使用'Stream.of()'和'Stream.empty()'? – akalikin

+0

不要調用'.orElse(null)',那麼你不需要測試'null'。所以'convertToList'的參數類型應該是'List >>',它可以在'join'之後執行'.filter(Optional :: isPresent).map(Optional :: get)'... – Holger

+0

@ Holger是的,這是一個在'convertToList'中進行過濾的選項(可選項或空值),我想盡一切努力,而'convertToList'可以是一個通用實用函數 – Amir

回答

1

的最好辦法很可能會改變convertToList(),以便它不返回列表的未來,但流代替:

private <T> CompletableFuture<Stream<T>> convertToFutureOfStream(List<CompletableFuture<T>> toConvert) { 
    return CompletableFuture.allOf(toConvert.stream().toArray(CompletableFuture[]::new)) 
      .thenApply(
        v -> toConvert.stream() 
          .map(CompletableFuture::join) 
      ); 
} 

這將是更多的可重複使用因爲該方法將允許更好的鏈接,並且不會強制呼叫者使用列表工作,同時仍然允許通過簡單的收集容易地獲得列表。

然後,您可以簡單地篩選流刪除空選配:通過改變convertToFutureOfStream()

CompletableFuture<List<String>> toReturn = asyncCall() 
    .thenCompose(listOfStuff -> convertToFutureOfStream(
      listOfStuff.stream() 
        .map(this::asyncCall2) 
        .collect(Collectors.toList()) 
     ) 
     .thenApply(stream -> 
       stream.filter(Optional::isPresent) 
         .map(Optional::get) 
         .collect(Collectors.toList()) 
     ) 

    ); 

你甚至可以改善這一點進一步採取流作爲參數以及:

private <T> CompletableFuture<Stream<T>> convertToFutureOfStream(Stream<CompletableFuture<T>> stream) { 
    CompletableFuture<T>[] futures = stream.toArray(CompletableFuture[]::new); 
    return CompletableFuture.allOf(futures) 
      .thenApply(v -> Arrays.stream(futures).map(CompletableFuture::join)); 
} 

(不幸的是,由於泛型類型的不同,這引發了一個未檢查的分配警告)

然後給出

CompletableFuture<List<String>> toReturn = asyncCall() 
    .thenCompose(listOfStuff -> convertToFutureOfStream(
       listOfStuff.stream().map(this::asyncCall2) 
      ) 
     .thenApply(stream -> 
       stream.filter(Optional::isPresent) 
         .map(Optional::get) 
         .collect(Collectors.toList()) 
     ) 

    );