在我的Java 11应用程序中,我想从存储库中获取产品更新。一个产品更新包含一个updateId
和一个productIds
列表以进行更新。
如果没有要使用updateId = X
更新的产品编号,我仍然想写到另一个已经处理过更新X
的表中; updateStatusRepository.setStatusProcessing(updateId)
仍应调用updateStatusRepository.setStatusProcessed(updateId)
和updateId
。
如果存在产品更新,则应在ProductProcessingService
中进行处理。
目前,groupingBy
和mapping
给了我一个带有null
条目的集合,而不是一个空集合,这就是为什么我后来删除所有null
产品ID的原因。
List<ProductUpdate> productUpdateList = updateStatusRepository.getProductUpdates();
Map<String, Set<String>> productUpdateMap = productUpdateList
.stream()
.collect(
Collectors.groupingBy(
ProductUpdate::getUpdateId,
Collectors.mapping(ProductUpdate::getProductNo, Collectors.toSet())));
productUpdateMap.forEach(
(updateId, productIds) -> {
try {
updateStatusRepository.setStatusProcessing(updateId);
productIds.remove(null);
if(!productIds.isEmpty()) {
productProcessingService.performProcessing(Lists.newArrayList(productIds));
}
updateStatusRepository.setStatusProcessed(updateId);
} catch (Exception e) {
//
}
});
如果可以使用mapping
,如果所有值均为null
,它可以直接传递一个空Set,则我更愿意。
有没有办法优雅地做到这一点?
答案 0 :(得分:10)
您可以使用Collectors.filtering
:
Map<String, Set<String>> productUpdateMap = productUpdateList
.stream()
.collect(Collectors.groupingBy(
ProductUpdate::getVersionId,
Collectors.mapping(ProductUpdate::getProductNo,
Collectors.filtering(Objects::nonNull,
Collectors.toSet()))));
我认为Collectors.filtering
符合您的确切用例:它将过滤掉null
个产品编号,如果所有产品编号都恰好是null
,则会保留一个空白集。
编辑:请注意,在这种情况下,使用Collectors.filtering
作为下游收集器与使用Stream.filter
进行收集之前不同。在后一种情况下,如果我们在收集之前过滤出具有null
产品编号的元素,则最终可能会得到一个地图,其中没有任何版本ID的条目,即,如果一个产品的所有产品编号均为null
特定版本ID。
来自Collectors.filtering
文档:
API注意:
filtering()
收集器在多级归约中(例如groupingBy
或partitioningBy
的下游)中最有用。例如,给定Employee
流,以累积每个部门中薪水超过特定阈值的员工:Map<Department, Set<Employee>> wellPaidEmployeesByDepartment = employees.stream().collect( groupingBy(Employee::getDepartment, filtering(e -> e.getSalary() > 2000, toSet())));
过滤收集器不同于流的
filter()
操作。在此示例中,假设在某个部门中没有薪水高于阈值的员工。如上所示,使用过滤器收集器将导致从该部门到空Set
的映射。如果改为执行流filter()
操作,则该部门将根本没有映射。
编辑2:我认为值得一提的是@Holger在评论中提出的替代方案:
Map<String, Set<String>> productUpdateMap = productUpdateList
.stream()
.collect(Collectors.groupingBy(
ProductUpdate::getVersionId,
Collectors.flatMapping(pu -> Stream.ofNullable(pu.getProductNo()),
Collectors.toSet())));