2016-02-01 33 views
6

Vì vậy, tôi đã tò mò về cách mã sau sẽ được viết lại hiệu quả hơn với API luồng java8.Tiêu thụ Dịch vụ Nghỉ ngơi theo cách chức năng

public static List<FlightInfo> getResults(String origin,List<String> destinations) { 

    final String uri = "https://api.searchflight.com/; 
    List<FlightInfo> results = new LinkedList<FlightInfo>(); 

    for(String destination:destinations) { 


      RestTemplate restTemplate = new RestTemplate(); 

      String params = getParams(origin,destination); 
      FlightInfo result = restTemplate.postForObject(uri+params,FlightInfo.class); 

      results.add(result); 
    } 

    return results; 

} 

Sau khi phương pháp này được thực hiện làm những gì mình đang làm và tôi nhận được danh sách các đối tượng FLightInfo, tôi đang chuyển đổi nó thành một dòng suối và sẽ được làm biến đổi khác nhau trên nó (nhóm bằng, vv). Bây giờ nó là khá apparant rằng đây là một hoạt động chạy dài. Hơn nữa nó thực sự kết hợp nhiều cuộc gọi còn lại với dịch vụ web, vì vậy tôi đã có hầu hết dữ liệu thu được khi tôi thực hiện cuộc gọi cuối cùng, nhưng tôi sẽ không bắt đầu xử lý nó trước khi toàn bộ phương thức trả về.

Có cách nào để làm tất cả điều đó một chút phản ứng hơn không? Tôi có thể trả về một dòng ngay lập tức và có các hoạt động trên luồng dữ liệu quá trình đó khi nó đi xuống đường ống hay đây là một chút quá nhiều để hỏi? Làm thế nào sẽ được thực hiện trong Java 8. Điều đó

Trả lời

5

Vâng tất cả phụ thuộc vào khi bạn cần kết quả. Nếu bạn muốn nó được tuần tự, điều này dưới đây vẫn là một cách phong nha như lười biếng của nó. Nhưng nó sẽ đun sôi tại một hoạt động đầu cuối (nói trong thời gian collect).

public static Stream<FlightInfo> getResults(String origin,List<String> destinations) { 
    final String uri = "https://api.searchflight.com/"; 
    return destinations.stream().map(destination -> { 
     RestTemplate restTemplate = new RestTemplate(); 
     String params = getParams(origin,destination); 
     FlightInfo result = restTemplate.postForObject(uri+params,FlightInfo.class); 
     return result; 
    })  
} 

Hoặc tôi sẽ làm điều đó với destinations.stream().parallel() nếu có thể. Đây là một kết quả hợp lý trong hầu hết các trường hợp. Nhưng nó vẫn sẽ không bắt đầu xử lý nó song song cho đến khi bạn gọi một hoạt động đầu cuối cho nó. Điều đó hoàn toàn có ý nghĩa.

Nhưng có vẻ với tôi rằng bạn mong muốn một loại người tiêu dùng sản xuất một thứ. Mà:

public static CompletableFuture<List<FlightInfo>> getResults(String origin,List<String> destinations) { 
    final String uri = "https://api.searchflight.com/"; 
    List<CompletableFuture<FlightInfo>> collect = destinations 
      .stream() 
      .map(destination -> CompletableFuture.supplyAsync(() -> { 
       RestTemplate restTemplate = new RestTemplate(); 
       String params = getParams(origin,destination); 
       FlightInfo result = restTemplate.postForObject(uri+params,FlightInfo.class); 
       return result;    
      })).collect(Collectors.toList()); 
    return sequence(collect);  //line-1 
} 

public static <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> com) { 
    return CompletableFuture.allOf(com.toArray(new CompletableFuture[com.size()])) 
      .thenApply(v -> com.stream() 
          .map(CompletableFuture::join) 
          .collect(Collectors.toList()) 
      ); 
} 

cho đơn giản, tại line-1 bạn chỉ có thể trở lại collect thay vì sequence(collect). Sau đó, bạn có thể lặp qua danh sách để tìm nạp từng giá trị.

Nhưng với sequence, bạn có một đối tượng CompletableFuture duy nhất cần lo lắng, sau đó bạn có thể kiểm tra các giá trị cùng một lúc nếu hoàn thành.

+0

Vì vậy, có chính xác khi nói rằng cách tiếp cận tương lai có thể hoàn thành sẽ chồng lấp quá trình xử lý bằng cách tìm nạp kết quả. Bởi vẻ ngoài của nó, đây thực sự là người tiêu dùng sản xuất được ánh xạ để sử dụng các luồng. Trong trường hợp đó, những gì bạn sẽ nói là những lợi ích của cách tiếp cận đặc biệt này trong việc thực hiện sản xuất - người tiêu dùng (ngoài việc ngắn gọn và thiếu bản mẫu của khóa học). Bằng cách này, tôi thực sự biết ơn vì giải pháp được cung cấp và tôi nghĩ điều đó thật tuyệt vời. Tôi chỉ cố gắng hiểu rõ hơn và đó là lý do tại sao hỏi các câu hỏi. Cảm ơn một lần nữa – Zahari

+1

Đơn giản chỉ cần ở trên CompletableFuture cung cấp một trừu tượng tốt đẹp cho người tiêu dùng sản xuất. Vâng, nếu nó trông xấu xí, đó là nhưng nếu sự xuất hiện của mô hình trên là cao trên cơ sở mã thì tôi khuyên bạn nên xem http://github.com/ReactiveX/RxJava/wiki. Nó cung cấp abstractions tốt đẹp như Observables (bạn có thể nghĩ giống như một dòng) mà bạn có thể có kết quả khi có sẵn. Bởi vì trừu tượng là âm thanh, bạn có một nắm chắc về tính biểu cảm – Jatin

Các vấn đề liên quan