如何使用 Java 8 流迭代多级映射?

Posted

技术标签:

【中文标题】如何使用 Java 8 流迭代多级映射?【英文标题】:How to iterate Multilevel Map using Java 8 stream? 【发布时间】:2021-12-20 00:13:10 【问题描述】:

我很擅长 Java 流,所以也许这不是最小的解决方案,但这是我想出的使用流来获得我认为你想要的东西的方法:

我们是否将 DishDiet 作为 POJO 并将 DishDietTest 作为主类? 我正在根据需要获取数据,但如何循环它? 如何使用流完成基于分类的打印?

public class DishDiet 

    private final String name;
    private final boolean vegetarian;
    private final int calories;
    private final Type type;
    private final CaloricLevel caloricLevel;

    public DishDiet(String name, boolean vegetarian, int calories, Type type, CaloricLevel caloricLevel) 
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
        this.caloricLevel = caloricLevel;
    

    public String getName() 
        return name;
    

    public boolean isVegetarian() 
        return vegetarian;
    

    public int getCalories() 
        return calories;
    

    public Type getType() 
        return type;
    

    public CaloricLevel getCaloricLevel() 
        return caloricLevel;
    

    @Override
    public String toString() 
        return name;
    

    
    public enum Type 
        MEAT, FISH, OTHER
    

    public enum CaloricLevel 
        DIET, NORMAL, FAT
    


public class DishDietTest 

    private static List<DishDiet> getAllDishDiet() 
        return Arrays.asList(new DishDiet("pork", false, 800, DishDiet.Type.MEAT, DishDiet.CaloricLevel.FAT),
                new DishDiet("beef", false, 700, DishDiet.Type.MEAT, DishDiet.CaloricLevel.FAT),
                new DishDiet("chicken", false, 400, DishDiet.Type.MEAT, DishDiet.CaloricLevel.DIET),
                new DishDiet("french fries", true, 530, DishDiet.Type.OTHER, DishDiet.CaloricLevel.NORMAL),
                new DishDiet("rice", true, 350, DishDiet.Type.OTHER, DishDiet.CaloricLevel.DIET),
                new DishDiet("season fruit", true, 120, DishDiet.Type.OTHER, DishDiet.CaloricLevel.DIET),
                new DishDiet("pizza", true, 550, DishDiet.Type.OTHER, DishDiet.CaloricLevel.NORMAL),
                new DishDiet("prawns", false, 300, DishDiet.Type.FISH, DishDiet.CaloricLevel.DIET),
                new DishDiet("salmon", false, 450, DishDiet.Type.FISH, DishDiet.CaloricLevel.NORMAL));
    

    public static void main(String[] args) 

        Map<DishDiet.Type, Map<DishDiet.CaloricLevel, List<DishDiet>>> dishesByTypeCaloricLevel = getAllDishDiet()
                .stream().collect(groupingBy(DishDiet::getType, groupingBy((dish -> 
                    if (dish.getCalories() <= 400)
                        return DishDiet.CaloricLevel.DIET;
                    else if (dish.getCalories() <= 700)
                        return DishDiet.CaloricLevel.NORMAL;
                    else
                        return DishDiet.CaloricLevel.FAT;
                

        ))));

        System.out.println(dishesByTypeCaloricLevel);

    


【问题讨论】:

【参考方案1】:

你的意思是这样吗?

    dishesByTypeCaloricLevel.forEach((type, innerMap) 
            -> 
                System.out.println(type);
                innerMap.forEach((cl, list)
                        -> 
                            System.out.println("    " + cl);
                            list.forEach(dd -> System.out.println("        " + dd));
                        );
            );

输出:

OTHER
    NORMAL
        french fries
        pizza
    DIET
        rice
        season fruit
FISH
    NORMAL
        salmon
    DIET
        prawns
MEAT
    FAT
        pork
    NORMAL
        beef
    DIET
        chicken

我没有使用流进行迭代和打印。我建议我们只使用MapListforEach 方法。用法类似,但更简单一些。

我们是否将 DishDiet 作为 POJO 并将 DishDietTest 作为主类? …

是的,没关系。

【讨论】:

太好了!非常感谢 Ole V.V【参考方案2】:
for(Map.Entry<DishDiet.Type, Map<DishDiet.CaloricLevel,List<DishDiet>>> t : dishesByTypeCaloricLevel.entrySet())
    DishDiet.Type key = t.getKey();
    for (Map.Entry<DishDiet.CaloricLevel,List<DishDiet>> e : 
        t.getValue().entrySet())
        System.out.println("OuterKey:" + key + " InnerKey: " + e.getKey()+ " VALUE:" +e.getValue());

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于如何使用 Java 8 流迭代多级映射?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 java 映射展平为列表,以便列表交替键和值?

将对象列表转换为映射Java 8流

如何使用流将列表转换为带有索引的地图 - Java 8?

通过流将带有列表的列表对象转换为Java 8中的映射[重复]

如何在 java 8 中迭代 JSONArray

如何使用包含键作为字符串和值作为映射迭代的ngFor循环映射进行迭代