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

使用Java Streams API动态将列表转换为枚举键的分组映射

解决方案

可以通过Java 8 Streams API实现完全不需要硬编码Category枚举值的转换,核心思路是自动遍历所有枚举值初始化PieSlice,再通过流式操作累加金额,新增枚举值时无需修改任何转换代码。

方法一:先初始化所有枚举对应的PieSlice,再累加金额

这种方式逻辑直观,先确保Map中包含所有Category的PieSlice(初始金额为0),再遍历LineItem完成金额累加:

List<LineItem> lineItems = getSomehow();

// 1. 初始化所有Category对应的PieSlice
Map<Category, PieSlice> sliceMap = Arrays.stream(Category.values())
    .collect(Collectors.toMap(
        Function.identity(), // 键为Category枚举本身
        category -> {
            PieSlice slice = new PieSlice();
            slice.setLabel(category.name()); // 可根据需求自定义label
            return slice;
        }
    ));

// 2. 遍历LineItem累加对应分类的金额
lineItems.forEach(item -> {
    Category category = item.getCategory();
    if (category == null) {
        throw new RuntimeException("line item " + item.getId() + " has null category");
    }
    PieSlice slice = sliceMap.get(category);
    // 理论上枚举值不会不存在,若出现非法值则抛出异常
    if (slice == null) {
        throw new RuntimeException("uncategorized line item: " + category);
    }
    slice.addAmount(item.getAmount());
});

方法二:先分组计算总金额,再生成PieSlice Map

这种方式先通过Stream计算每个Category的总金额,再映射为PieSlice,同时自动补充没有数据的枚举值:

List<LineItem> lineItems = getSomehow();

// 1. 分组计算每个Category的总金额
Map<Category, BigDecimal> totalAmountMap = lineItems.stream()
    .peek(item -> {
        // 提前校验非法分类(包括null)
        if (item.getCategory() == null) {
            throw new RuntimeException("line item " + item.getId() + " has null category");
        }
    })
    .collect(Collectors.groupingBy(
        LineItem::getCategory,
        // 累加同一分类的金额,初始值为0
        Collectors.reducing(BigDecimal.ZERO, LineItem::getAmount, BigDecimal::add)
    ));

// 2. 生成包含所有Category的PieSlice Map
Map<Category, PieSlice> sliceMap = Arrays.stream(Category.values())
    .collect(Collectors.toMap(
        Function.identity(),
        category -> {
            PieSlice slice = new PieSlice();
            slice.setLabel(category.name());
            // 没有数据的分类自动使用0作为金额
            slice.setValue(totalAmountMap.getOrDefault(category, BigDecimal.ZERO));
            return slice;
        }
    ));

核心优势

  • 无需关注枚举具体值:通过Category.values()自动获取所有枚举实例,新增Category枚举值时,转换代码完全不需要修改。
  • 异常处理更严谨:可以在流式操作中提前校验非法分类(如null或不存在的枚举值),避免后续逻辑出错。
  • 代码更简洁易维护:替代了繁琐的if-else分支,逻辑清晰,可读性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:01:01