[英]How to reduce on groups and return a sorted list with the Java 8 Stream API
有没有一种简单的方法可以通过归约和排序来完成以下groupBy? 我无法弄清楚如何避免拆开Optional或为什么甚至可以从Optional开始。
给定的List<Response>
包含许多响应。 对于每一组的Response
实体(按分组taskId
),我想只有Response
该组与最新submissionDateTime
。 所述submissionDateTime
是一个Optional<OffsetDateTime>
于Response
实体。
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());
还要注意的是, submissionDateTime
是Response
接口上的Optional<OffsetDateTime>
。 实际的submissionDateTime
不是字段级Optional
。
...或者为什么还有可选的“开头”。
这是减少空流时的安全措施。 在那种情况下,最大值是多少? 这是未知的,因此可能存在或可能没有实际的返回值。 那是可选的出现的地方。
但是在这种情况下,您始终Optional.get
安全地调用Optional.get
,因为groupingBy
产生的groupingBy
永远不会为空。 如果组中没有元素,则永远不会为其创建列表。 (但是,还原收集器不知道这一点。)
您的方法很好。
PS,您也可以直接使用maxBy
收集器。
这使它稍微简单一点。 我认为没有必要将maxBy
包装在reduce
。
关于您有关Optional#get
的必要性的问题:假定其原因是在减少之后,结果可能是“空”的。 因此是可选的。 在您的情况下,如果Optional确实为空,则调用Optinal#get
会导致异常。 由于您执行maxBy
操作,并且您的Comparator处理null,所以我想您已经保存了。 否则,您应该先过滤。
responses.stream()
.collect(
Collectors.groupingBy(Response::getTaskId,
Collectors.maxBy(bySubmissionDate))).values().stream()
.map(Optional::get)
.collect(Collectors.toList());
另一个注意事项:您的SubmitDateTime似乎是Optional类型。 不建议使用Optionals作为字段类型。 请参阅为什么在参数中不使用Java 8的Optional
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.