首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java stream: groupingBy和flatMapping密钥

Java stream: groupingBy和flatMapping密钥
EN

Stack Overflow用户
提问于 2019-03-26 23:04:45
回答 3查看 202关注 0票数 1

假设我有一个country对象列表,其中包含在该国家使用的语言列表,如下所示:

代码语言:javascript
复制
class Country {
    List languages; 
}

我想创建以下格式的地图:Map>,使得每种语言都映射到国家对象列表。例如:

代码语言:javascript
复制
"French" -> [Country:France, Country:Canada],
"English" -> [Country:UK, Country:US]

性能是这里的一个问题,所以我想避免多次迭代和查找。我试过使用groupingBy,但是我该如何flatMap密钥集?

例如,这将导致Map, List>

代码语言:javascript
复制
countries.stream()
    .collect(Collectors.groupingBy(country -> country.getLanguages(), toList()));
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-03-26 23:21:09

既然您似乎很关心性能,那么就不要使用streams来完成这个简单的任务:

代码语言:javascript
复制
Map> countriesByLanguage = new HashMap<>();
for (Country country : countries) {
    for (String language : country.getLanguages()) {
        countriesByLanguage.computeIfAbsent(language, k -> new ArrayList<>())
                           .add(country);
    }
}
票数 1
EN

Stack Overflow用户

发布于 2021-02-25 04:23:07

您可以使用以下命令来完成此操作小溪中的小溪如下所示:首先迭代国家列表,然后迭代嵌套的语言列表并准备«language, country»对,然后收集它们来映射:

代码语言:javascript
复制
public static void main(String[] args) {
    List countries = List.of(
            new Country("France", List.of("French")),
            new Country("Canada", List.of("French")),
            new Country("UK", List.of("English")),
            new Country("US", List.of("English")));

    Map> map = countries.stream()
            // Stream>
            .flatMap(country -> country.getLanguages().stream()
                    .map(lang -> Map.entry(lang, country)))
            .collect(Collectors.toMap(
                    // key - language
                    Map.Entry::getKey,
                    // value - List
                    entry -> new ArrayList<>(List.of(entry.getValue())),
                    // merge duplicates, if any
                    (list1, list2) -> {
                        list1.addAll(list2);
                        return list1;
                    }
            ));

    // output
    map.forEach((k, v) -> System.out.println(k + "=" + v));
    //English=[Country:UK, Country:US]
    //French=[Country:France, Country:Canada]
}
代码语言:javascript
复制
static class Country {
    String name;
    List languages;

    public Country(String name, List languages) {
        this.name = name;
        this.languages = languages;
    }

    public List getLanguages() {
        return languages;
    }

    @Override
    public String toString() {
        return "Country:" + name;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2019-03-26 23:14:14

这样就可以了:

代码语言:javascript
复制
countries.stream()
        .flatMap(country -> country.getLanguages()
                .stream()
                .map(lang -> new SimpleEntry<>(lang,
                        new ArrayList<>(Arrays.asList(country)))))
        .collect(Collectors.toMap(
                Entry::getKey,
                Entry::getValue,
                (l1, l2) -> {
                    l1.addAll(l2);
                    return l2;
                }));
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55360374

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档