我正在尝试将3级嵌套列表转换为Nested HashMap。
同一函数的声明为:
Map<Key1, Map<Key2, List<String>>> transformToMap (List<Obj1> inputList)
inputList
内部具有嵌套列表,而该列表又具有嵌套列表。
我编写的代码使用传统的for循环,如下所示:
private Map<Key1 , Map<Key2, List<String>>> reverseLookup(List<Key2> key2List){
Map<Key1 , Map<Key2, List<String>>> resultMap = new HashMap<>();
key2List.forEach(key2->{
List<ElementObject> elementObjects = key2.getElementObjects();
elementObjects.forEach(elementObject->{
final String name = elementObject.getName();
elementObject.getApplicablePeriods().forEach(applicablePeriod-> {
Key1 key1 = applicablePeriod.getKey1();
Map<Key2, List<String>> map2 = resultMap.get(key1);
if(map2 == null){
map2 = new HashMap<>();
}
List<String> stringList = map2.get(key2);
if(stringList == null){
stringList = new ArrayList<>();
}
stringList.add(name);
map2.put(key2, stringList);
resultMap.put(key1, map2);
});
});
});
return resultMap;
}
相同的类结构如下:
class Key2{
List<ElementObject> elementObjects;
//getters & setters
}
class ElementObject {
String name;
//few more params
List<ApplicablePeriod> applicablePeriods;
//getters & setters
}
class ApplicablePeriod{
Key1 key1;
//getters & setters
}
class Key1{
//some parameters
//getters & setters
}
上面的代码符合我的期望。
使用Collectors.toMap
将其转换为流lambda的有效方法是什么?
我尝试了以下操作:
inputList
.stream()
.flatMap(item -> item.getObj2List().stream())
.flatMap(nestedItem -> nestedItem.getKeyList().stream())
.collect(Collectors.toMap(a-> a.get()))
但没有得到Collectors.toMap
中下一步应该做什么。
无法处理仅在第3个for循环之前使用的final String name = nestedItem.getName();
。
让我知道解决此问题的方法。
答案 0 :(得分:0)
我没有任何测试数据来查看它是否创建了与您的传统代码类似的东西。但是看看这个,如果有帮助,请告诉我:
key2List.stream().flatMap((key2) -> key2.elementObjects.stream().map((element) -> new AbstractMap.SimpleImmutableEntry<>(key2, element)))
.flatMap((entry) -> entry.getValue().applicablePeriods.stream().map((period) -> new AbstractMap.SimpleImmutableEntry<>(period.key1, new AbstractMap.SimpleImmutableEntry<>(entry.getKey(), entry.getValue().name))))
.collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList())))));
答案 1 :(得分:0)
事实上,问题是你想访问同一个 Stream
内的多个抽象级别,这通常是不可能的,除非你有
我以第二种方式修复它。
我正在使用 java-16 和以下功能
Collectors#mapMulti
Collectors#groupingBy
record
private Map<Key1, Map<Key2, List<String>>> reverseLookup(List<Key2> key2List) {
record HolderObject(Key2 key2, ElementObject elementObject, ApplicablePeriod applicablePeriod){}
return key2List.stream()
.mapMulti((Key2 key2, Consumer<HolderObject> consumer) -> {
List<ElementObject> elementObjects = key2.getElementObjects();
elementObjects.forEach(elementObject ->
elementObject.getApplicablePeriods().forEach(applicablePeriod -> {
consumer.accept(new HolderObject(
key2,
elementObject,
applicablePeriod
));
})
);
})
.collect(Collectors.groupingBy(
h -> h.applicablePeriod().getKey1(),
Collectors.groupingBy(
HolderObject::key2,
Collectors.mapping(
h -> h.elementObject().getName(),
Collectors.toList()
)
)
));
}
这是一个java-8兼容的解决方案
private Map<Key1, Map<Key2, List<String>>> reverseLookup(List<Key2> key2List) {
return key2List
.stream()
.flatMap(key2 -> key2.getElementObjects()
.stream()
.flatMap(elementObject -> elementObject.getApplicablePeriods()
.stream()
.map(applicablePeriod -> new HolderObject(
key2,
elementObject,
applicablePeriod
))))
.collect(Collectors.groupingBy(
h -> h.getApplicablePeriod().getKey1(),
Collectors.groupingBy(
HolderObject::getKey2,
Collectors.mapping(
h -> h.getElementObject().getName(),
Collectors.toList()
)
)
));
}
@Value
public static class HolderObject {
Key2 key2;
ElementObject elementObject;
ApplicablePeriod applicablePeriod;
}