Convert a list of maps to a map of lists using Java Streams

I would like to convert a list of maps to a map of lists. It is guaranteed that all the maps have the same keys.

For example, the following list

[{key1: val1, key2: val2}, {key1: val3, key2: val4}]

gets converted to

{key1: [val1, val3], key2: [val2, val4]}

The below code does it using for loops

List<Map<String, Object>> data = getData();

Map<String, List<Object>> result = new HashMap<>();

for (Map<String, Object> element: data) {
    element.forEach((key, val) -> {
        if (result.containsKey(key))
            result.get(key).add(val);
        else
            result.put(key, Arrays.asList(val));
    });
}

How would I be able to achieve the same result using streams?

Answer

E.g. like this, relying on the collect stage of java streams.

 List<Map<String, Object>> data = new ArrayList<>();

 HashMap<String, List<Object>> transposed = data.stream()
            .flatMap(i -> i.entrySet().stream())
            .collect(groupingBy(
                    Map.Entry::getKey,
                    HashMap::new,
                    mapping(Map.Entry::getValue, toCollection(ArrayList::new))));

There are a number of such application on SO (e.g. this one), though not precisely tailored to this example.

Leave a Reply

Your email address will not be published. Required fields are marked *