Skip to content
Advertisement

Stream groupBy to nested maps with casting

Need to calculate total number by gender from below structure of nested Maps. But as data stored as Object need to cast it at every iteration. After grouping not able to cast last leaf Map to calculate and filter date object.

Map<String, Object> total = new HashMap<>();
Map<String, Object> mass = new HashMap<>();
Map<String, Object> ny = new HashMap<>();
Map<String, Object> male = new HashMap<>();
male.put("2021", 17);
male.put("2020", 98);
male.put("lastdate", new Date());
Map<String, Object> female = new HashMap<>();
female.put("2021", 12);
female.put("2020", 87);
female.put("lastdate", new Date());
mass.put("male", male);
mass.put("female", female);
ny.put("male", male);
ny.put("female", female);
total.put("MA", mass);
total.put("NY", ny);

Applied below stream,

Object mm = total.values().stream().map(x -> (Map<String, Object>) x)
            .map(Map::entrySet).flatMap(Collection::stream)
            .collect(
                    Collectors.groupingBy(Map.Entry::getKey),
                    Collectors.toMap(x -> (Map<String, Object>) x) // Not Working both toMapping() too
            );

/*
Final required output as Map
male=115
female=99
 */

Advertisement

Answer

It is a rather unusual way to store data. I would recommend you to implement appropriate classes, such as person with the appropriate fields like gender, age, weight etc.

But if you want to stick with your data structure, something like below should work:

Map<String,Integer> result =
total.values()
        .stream()
        .map(e -> (Map<String,Object>) e)
        .findAny()
        .get()
        .entrySet()
        .stream()
        .collect(
                Collectors.toMap(Map.Entry::getKey,
                        m -> ((Map<String,Object>) m.getValue()).values()
                                .stream()
                                .filter(Integer.class::isInstance)
                                .mapToInt(Integer.class::cast)
                                .sum()));
Advertisement