我有Documents
对象,我想按文档ID对其进行分组。对它们进行分组后,我想得到它们的"最大值";。这就是我目前所拥有的:
List<Document> docList = getDocuments(...);
Map<Long, Document> docIdsToLatestDocVersions = docList.stream()
.collect(Collectors.groupingBy(
Document::getDocumentId,
Collectors.reducing(BinaryOperator.maxBy(Comparator.comparing( Function.identity() ))
));
文档类别:
class Document {
int documentId;
int majorVersion;
int minorVersion;
@Override
public int compareTo(Document document) {
return new CompareToBuilder()
.append(this.getDocumentId(), document.getDocumentId())
.append(this.getMajorVersion(), document.getMajorVersion())
.append(this.getMinorVersion(), document.getMinorVersion())
.toComparison();
}
}
重要的是,我已经实现了compareTo函数。我不知道该在groupingBy
子句的reducer
自变量中放什么。我也试过:
Map<Long, Document> docIdsToLatestDocVersions = docList.stream()
.collect(Collectors.toMap(
Document::getDocumentId, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(d -> d))));
但无济于事。
在您的第一个代码段中,Collectors.reducing
将返回一个Optional,您需要将结果映射的类型更改为Map<Integer, Optional<Document>>
,或者将reduction收集器包装到collectingAndThen
收集器中以打开包装Optional:
Map<Integer, Document> docIdsToLatestDocVersions =
docList.stream()
.collect(Collectors.groupingBy(Document::getDocumentId,
Collectors.collectingAndThen(
Collectors.reducing(BinaryOperator.maxBy(Document::compareTo)),
Optional::get)));
但正如您已经提到并尝试过的,每当您在分组后遇到Optionals时,最好检查Collectors.toMap
是否是更好的选择。在这种情况下,它确实更可读:
Map<Integer, Document> docIdsToLatestDocVersions_second =
docList.stream()
.collect(Collectors.toMap(Document::getDocumentId,
Function.identity(),
BinaryOperator.maxBy(Document::compareTo)));