如何让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
相关产品推荐
相关产品推荐

