Java的收集与分组和映射`set`,但需要一个空集,如果所有的值是`null`

问题描述 投票:6回答:1

在我的Java应用程序11,我想从一个存储库中获得产品更新。一个产品更新有updateIdproductIds的名单进行更新。

  • 如果有应与updateId = X更新进行更新没有产品编号,我还是要写信给我已经处理了更新X另一个表; updateStatusRepository.setStatusProcessing(updateId)updateStatusRepository.setStatusProcessed(updateId)仍然应该叫这个updateId
  • 如果不存在产品的更新,他们应该在ProductProcessingService进行处理。

就目前而言,groupingBymapping给我一套具有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

有没有一种方法能够完美地做到这一点?

java java-stream collectors
1个回答
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())));
© www.soinside.com 2019 - 2024. All rights reserved.