【问题标题】:Creating a map from nested lists从嵌套列表创建地图
【发布时间】:2020-04-26 11:26:34
【问题描述】:

假设有 3 个类:

class Level1 {
    int idLevel1;
    List<Level2> level2list;    
}

class Level2 {
    int idLevel2;
    List<Level3> level3list;    
}   

class Level3 {  
    int idLevel3;
    String name;
}   

假设有一个称为初始状态的 Level1 对象列表

List<Level1> initialList = new ArrayList<>();

我想从 initialList 创建一个地图,其中:

 - Key: is idLevel1
 - Value: is list of all idLevel3 , corresponding to idLevel1

我可以使用 for 循环来实现这一点,但我想使用 Java 8 特性(流和函数)以更优雅的方式实现这一点。 我尝试使用 Collectors.toMap() 也尝试过分组,但我无法获得所需的地图。

【问题讨论】:

  • 一串两个flatMap,好像。
  • 向我们展示您的尝试 - 除了给出答案之外,我们还可以根据您的尝试帮助您:)
  • Elegant 不一定表示best
  • 不应该Level2类定义中的level2List真的是level3List吗?
  • @WJS 是的,你是对的,应该是level3List

标签: java collections java-8 functional-programming java-stream


【解决方案1】:

与其他人类似的方法:

Map<Integer, List<Integer>> map = initialList.stream()
        .collect(Collectors.toMap(Level1::getIdLevel1,
                lv1 -> lv1.getLevel2list().stream()
                        .flatMap(lv2 -> lv2.getLevel3list().stream().map(Level3::getIdLevel3))
                        .collect(Collectors.toList())));

我在你的课程中添加了 getter 并将一个名称从 List&lt;Level3&gt; level2list; 更改为 List&lt;Level3&gt; level3list;

class Level1 {
    int idLevel1;
    List<Level2> level2list;

    public int getIdLevel1() {
        return idLevel1;
    }

    public List<Level2> getLevel2list() {
        return level2list;
    }
}

class Level2 {
    int idLevel2;
    List<Level3> level3list;

    public List<Level3> getLevel3list(){
        return level3list;
    }
}

class Level3 {
    int idLevel3;
    String name;

    public int getIdLevel3() {
        return idLevel3;
    }
}

【讨论】:

    【解决方案2】:

    通过对应于idLevel1,我假设您想要一个特定idLevel1chain 中的所有idlevel3 的列表

    因此,对于某些level1 id,可能会有一个level3 ids 列表,对于不同的level1 id,可能会有一个不同的level3 ids 列表。

    基于此,这就是我想出的。

            Map<Integer, List<Integer>> map = initialList
                    .stream()
                    .collect(Collectors
                            .toMap(lv1 -> lv1.idLevel1,
                                    lv1 -> lv1.level2list
                                            .stream()
                            .flatMap(lv2 -> lv2.level3list
                                    .stream())
                            .map(lv3 -> lv3.idLevel3)
                            .collect(Collectors.toList())));
    

    【讨论】:

    • 这和existing answer不一样吗?
    • @Naman。不。我对要求的解释不同,并且没有通过将 level1ID 与 level3ID 进行比较来进行任何过滤,因为这对我来说毫无意义(我可能是错的,但我认为 OP 会让我知道)。
    • 那可能是worth a comment 而不是答案。由于现有答案中收集的类型在逻辑上仍然保持不变。
    【解决方案3】:

    我有这个是有效的,但我没有数据来测试它,所以请测试它并给我反馈:)。

    Map<Integer, List<String>> map = 
            initialList.stream()
                    .collect(Collectors.toMap(f -> f.idLevel1,
                    f -> f.level2list.stream()
                    .flatMap(f2 -> f2.level2list.stream())
                    .collect(Collectors.toList()).stream()
                    .filter(f3 -> f3.idLevel3 == f.idLevel1)
                    .map(f3 -> f3.name).collect(Collectors.toList())));
    

    【讨论】:

    • 您的方法几乎是正确的,我认为不需要过滤器。感谢您尝试帮助我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 2022-10-22
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多