4

这是我到目前为止所拥有的:

Map<Care, List<Correlative>> mapOf = quickSearchList
                .stream()
                .map(QuickSearch::getFacility)
                .collect(Collectors.flatMapping(facility -> facility.getFacilityCares().stream(),
                    Collectors.groupingBy(FacilityCare::getCare,
                        Collectors.mapping(c -> {
                            final Facility facility = new Facility();
                            facility.setId(c.getFacilityId());
                            return Correlative.createFromFacility(facility);
                        }, Collectors.toList()))));

我有一个快速搜索列表。快速搜索中的每个项目都有一个设施,如下所示:

public class QuickSearch {
  Facility facility;
}

在每个设施中,都有一个 FacilityCare 列表,如下所示:

public class Facility {
  List<FacilityCare> facilityCares;
}

最后,FacilityCare 具有 Care 属性,如下所示:

public class FacilityCare {
   Care care;
}

现在,想法是将 QuickSearch 列表转换为<Care, List<Correlative>>. 在上面的示例中,mapping() 函数中的代码是伪造的。FacilityCare 只有facilityID 而没有Facility 实体。我希望在 flatMapping 中作为参数的设施对象在 mapping() 函数中再次成为我的参数,如下所示:

Collectors.mapping(c -> Correlative.createFromFacility(facility)) 

其中“facility”与 flatMapping 中的对象相同。

有什么办法可以做到这一点?请让我知道是否需要进一步解释。

编辑: 这是一个没有充分利用收集器的解决方案。

final Map<Care, List<Correlative>> mapToHydrate = new HashMap<>();

 quickSearchList
  .stream()
  .map(QuickSearch::getFacility)
  .forEach(facility -> {
    facility.getFacilityCares()
      .stream()
      .map(FacilityCare::getCare)
      .distinct()
      .forEach(care -> {
        mapToHydrate.computeIfAbsent(care, care -> new ArrayList<>());
        mapToHydrate.computeIfPresent(care, (c, list) -> {
          list.add(Correlative.createFromFacility(facility));
          return list;
        });
      });
    });
      
4

3 回答 3

2

这是我根据提供的信息得出的。和存储在临时数组中FacilityCare稍后在所需映射中进行处理。

Map<Care, List<Correlative>> mapOf = quickSearchList.stream()
        .map(QuickSearch::getFacility)
        .flatMap(facility -> facility
                .getFacilityCares().stream()
        .map(facCare->new Object[]{facility, facCare.getCare()}))
        .collect(Collectors.groupingBy(obj->(Care)obj[1], Collectors
                .mapping(obj -> Correlative.createFromFacility(
                        (Facility)obj[0]),
                        Collectors.toList())));

我准备了一些简单的测试数据,假设我了解最终目标,这似乎有效。对于每种care提供的类型,它会将提供该类型的所有设施care放在一个相关的列表中facilities

于 2020-10-13T01:54:56.587 回答
2

有时,流不是最好的解决方案。情况似乎是这样,因为您facility在沿着管道走下去时会丢失每个实例。

相反,您可以按如下方式进行:

Map<Care, List<Correlative>> mapToHydrate = new LinkedHashMap<>();
quickSearchList.forEach(q -> {
    Facility facility = q.getFacility();
    facility.getFacilityCares().forEach(fCare -> 
        mapToHydrate.computeIfAbsent(fCare.getCare(), k -> new ArrayList<>())
                    .add(Correlative.createFromFacility(facility)));
});

这使用的返回值Map.computeIfAbsent(它是新创建的关联列表或已经存在的关联列表)。

从您的问题中不清楚为什么在将它们添加到地图之前需要特别注意。


编辑:从 Java 16 开始,您可能想要使用Stream.mapMulti

Map<Care, List<Correlative>> mapToHydrate = quickSearchList.stream()
    .map(QuickSearch::getFacility)
    .mapMulti((facility, consumer) -> facility.getFacilityCares()
        .forEach(fCare -> consumer.accept(Map.entry(fCare.getCare(), facility))))
    .collect(Collectors.groupingBy(
        e -> e.getKey(), 
        Collectors.mapping(
            e -> Correlative.createFromFacility(e.getValue()),
            Collectors.toList())));
于 2020-10-13T14:52:47.393 回答
1

受@fps 回答的启发,我想出了一个暂时可行的解决方案(Java16 之前)。

Map<Care, List<Correlative>> mapOf = quickSearchList
            .stream()
            .map(QuickSearch::getFacility)
            .map(expandIterable())
            .collect(
                Collectors.flatMapping(map -> map.entrySet().stream(),
                    Collectors.groupingBy(Map.Entry::getKey,
                        Collectors.mapping(entry -> Correlative.createFromFacility(entry.getValue()),
                            Collectors.toList()
                        )
                    )
                ));
    }

    public Function<Facility, Map<Care, Facility>> expandIterable() {
        return facility -> facility.getFacilityCares()
            .stream()
            .map(FacilityCare::getCare)
            .distinct()
            .collect(Collectors.toMap(c -> c, c -> facility));
    }

基本上,我添加了一个方法调用,该方法调用返回一个函数,该函数以 Facility 作为参数并返回一个护理地图作为键,以 Facility 作为值。该映射用于前一个流的集合中。

于 2020-10-13T20:20:22.240 回答