簡體   English   中英

Java 8 Lambdas flatmapping、groupingBy 和 mapping 以獲取 T 和 List 的 Map<K>

[英]Java 8 Lambdas flatmapping, groupingBy and mapping to get a Map of T and List<K>

這是我到目前為止所擁有的:

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 的 List 轉換為<Care, List<Correlative>>的 Map。 在上面的示例中, mapping() 函數中的代碼是偽造的。 FacilityCare 只有設施 ID 而沒有設施實體。 我希望在 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;
        });
      });
    });
      

這是我根據提供的信息得出的結論。 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列表中。

有時,流並不是最好的解決方案。 情況似乎是這樣,因為在沿着管道向下時,您正在丟失每個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())));

受到@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 作為參數,並返回一個 Map of Care 作為鍵,Facility 作為值。 該映射用於前一個流的集合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM