【问题标题】:Java8 How to convert 3-level nested list into nested HashMap using stream and lambdaJava8如何使用流和lambda将3级嵌套列表转换为嵌套HashMap
【发布时间】:2020-02-02 10:17:58
【问题描述】:

我正在尝试将 3 级嵌套列表转换为嵌套 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 中的下一步应该是什么。 无法处理在第三个 for 循环之前使用的 final String name = nestedItem.getName();

告诉我解决这个问题的方法。

【问题讨论】:

  • 到目前为止你尝试过什么?
  • 我正在尝试类似:inputList.stream().flatMap(item -&gt; item.getObj2List().stream()).flatMap(nestedItem -&gt; nestedItem.getKeyList().stream()).collect(Collectors.toMap(a-&gt; a.get())) 但没有得到Collectors.toMap 的下一步应该是什么。无法处理在第三个 for 循环之前使用的 final String name = nestedItem.getName();
  • 编辑问题并更新它,以便人们进一步帮助您。
  • 这是在编译吗?似乎当您执行nestedMap.put(item,stringList); 时,您的项目类型为Obj1 而它应该是Key2
  • Key2 本质上是一个包含列表的复合对象。你真的想用它作为结果地图的键吗?那么equals() 是如何定义的呢?

标签: java lambda java-8 hashmap java-stream


【解决方案1】:

我没有任何测试数据来查看它是否会创建与您的传统代码相似的内容。但是看看这个,如果有帮助,请告诉我:

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())))));

【讨论】:

    【解决方案2】:

    事实上,问题在于您想访问同一个Stream 内的多个抽象级别,这通常是不可能的,除非您有

    • 嵌套流
    • 可以保存对更高对象的引用的对象

    我用第二种方法修复了它。

    我正在使用 和以下功能

    • 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()
                                )
                        )
                ));
    }
    

    这是一个 兼容的解决方案

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-08
      • 2020-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      相关资源
      最近更新 更多