You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Java Streams groupingBy结果包含枚举所有值(含空列表)

如何让Java Stream groupingBy包含枚举所有值(无数据时显示空列表)

问题场景

现有WorldCup类和Country枚举,通过Stream的groupingBy按冠军国家分组后,结果Map里只包含有对应数据的枚举项。需要实现让Map包含所有枚举值,无对应数据的项显示为空列表。

代码示例

WorldCup类

public class WorldCup {
    int year;
    Country champion;
    // 全参构造器、getter/setter等
}

Country枚举

public enum Country {
    Brazil, France, USA
}

当前分组代码

WorldCup wc94 = new WorldCup(1994, Country.Brazil);
WorldCup wc98 = new WorldCup(1998, Country.France);
List<WorldCup> wcList = new ArrayList<>();
wcList.add(wc94);
wcList.add(wc98);

Map<Country, List<Integer>> championsMap = wcList.stream()
    .collect(Collectors.groupingBy(WorldCup::getChampion, Collectors.mapping(WorldCup::getYear, Collectors.toList())));

当前结果

Brazil: [1994]
France: [1998]

期望结果

Brazil: [1994]
France: [1998]
USA: []

简洁实现方案

方案一:先分组,再补全枚举项

这是最直观高效的方式,先完成常规分组,再遍历所有枚举值,为不存在的项添加空列表:

Map<Country, List<Integer>> championsMap = wcList.stream()
    .collect(Collectors.groupingBy(WorldCup::getChampion, Collectors.mapping(WorldCup::getYear, Collectors.toList())));

// 遍历所有枚举值,补全空列表
for (Country country : Country.values()) {
    championsMap.putIfAbsent(country, new ArrayList<>());
}

优点:只需要遍历一次原始列表做分组,再遍历一次枚举(枚举数量通常很少),性能最优。

方案二:用Collectors.toMap一步完成

直接基于所有枚举值构建Map,每个枚举值对应过滤后的年份列表:

import java.util.function.Function;

Map<Country, List<Integer>> championsMap = Arrays.stream(Country.values())
    .collect(Collectors.toMap(
        Function.identity(), // 键为枚举本身
        country -> wcList.stream()
            .filter(wc -> wc.getChampion().equals(country))
            .map(WorldCup::getYear)
            .collect(Collectors.toList()) // 值为对应年份列表,无数据则为空
    ));

优点:代码是链式调用,一步到位,适合枚举数量较少的场景。


内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 08:45:46