2017-05-08 60 views
0

是否有一個簡單的方法來做以下groupBy減少和排序?我無法弄清楚如何避免必須拆開可選或爲什麼可選項甚至在那裏開始。如何減少組和返回一個排序列表與Java 8流API

給定List<Response>包含許多回應。對於每組Response實體(按taskId分組),我只希望該組的Response最新的submissionDateTimesubmissionDateTimeResponse實體上的Optional<OffsetDateTime>

Comparator<Response> bySubmissionDate = Comparator.comparing(
    r -> r.getSubmissionDateTime().orElse(OffsetDateTime.MAX) 
); 
List<Response> responses = responses.stream() 
     .collect(Collectors.groupingBy(
      Response::getTaskId, 
      Collectors.reducing(maxBy(bySubmissionDate)) 
     )).values().stream() 
     .map(Optional::get) 
     .sorted(bySubmissionDate) 
     .collect(Collectors.toList()); 

當然,必須有更好的方法來做到這一點。最終的順序很重要,因此最終的標準爲.sorted(bySubmissionDate)

編輯 給出的答覆,我已經能夠減少代碼如下:另外值得注意的

List<Response> responses = responses.stream() 
      .collect(Collectors.groupingBy(
       ResponseComplete::getTaskId, 
       Collectors.maxBy(bySubmissionDate) 
      )).values().stream() 
      .map(Optional::get) 
      .sorted(bySubmissionDate) 
      .collect(Collectors.toList()); 

submissionDateTimeResponse接口上Optional<OffsetDateTime>。實際的submissionDateTime不是字段級的Optional

回答

2

...或者爲什麼選擇性甚至在那裏開始。

這是減少空流時的安全措施。這種情況下的最大值是多少?這是未知的,所以有可能或可能不會有實際的回報價值。這就是選件進來的地方。

但是在這種情況下,您總是可以安全地撥打Optional.get,因爲從groupingBy產生的組永遠不會爲空。如果組中沒有元素,則不會爲其創建列表。 (但是,還原收集器不知道這一點)。

您的方法很好。


p.S.,你也可以直接使用maxBy收集器。

0

這使它變得更簡單一點。我認爲沒有必要將maxBy換成reduce

關於你對Optional#get的必要性的疑問:假設原因是,在減少後,結果可能是「空的」。因此可選。 在你的情況,如果可選確實是空的,調用Optinal#get會導致異常。既然你做了一個maxBy操作,你的比較器處理爲空,我猜你是保存的。否則,你應該先過濾。

responses.stream() 
    .collect(
     Collectors.groupingBy(Response::getTaskId, 
     Collectors.maxBy(bySubmissionDate))).values().stream() 
    .map(Optional::get) 
    .collect(Collectors.toList()); 

另一個注意事項:看起來你的submissionDateTime類型是可選的。不建議使用Optionals作爲字段類型。見Why should Java 8's Optional not be used in arguments

+0

該字段本身是一個'OffsetDateTime'。 'Optional '來自接口。對不起,我認爲我沒有在我的問題中說清楚。 – varcharmander

+0

@varcharmander不需要對不起:)。在這種情況下,由於getter約定,可能使用getOptionalSubmissionDateTime。只是一個側面說明。 –