Search code examples
javajava-streamflatmap

Java streams: groupingBy and flatMapping keys


Say I have a list of country objects that contain lists of languages spoken in that country, like so:

class Country {
    List<String> languages; 
}

I would like to create a map in the following format: Map<String, List<Country>>, such that a each language maps to a list of Country objects. E.g.:

"French" -> [Country:France, Country:Canada],
"English" -> [Country:UK, Country:US]

Performance is an issue here, so I would like to avoid multiple iterations and lookups. I have tried using groupingBy, but how do I flatMap the keyset?

Example, this results in Map<List<String>, List<Country>>:

countries.stream()
    .collect(Collectors.groupingBy(country -> country.getLanguages(), toList()));

Solution

  • Since you seem to care about performance, don't use streams for this simple task:

    Map<String, List<Country>> countriesByLanguage = new HashMap<>();
    for (Country country : countries) {
        for (String language : country.getLanguages()) {
            countriesByLanguage.computeIfAbsent(language, k -> new ArrayList<>())
                               .add(country);
        }
    }