[英]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;
});
});
});
這是我根據提供的信息得出的結論。 Facility
和Care
存儲在臨時數組中,稍后在所需的地圖中進行處理。
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.