如何利用Java8分组求和及排序等操作

2024-06-17 14:21:46 浏览数 (1)

一、背景

在Java 8中,Stream API为开发者提供了一种高效且声明性的方式来处理数据集合,在实际开发中也是经常使用。其中,Collectors类提供了丰富的收集器(Collector)用于完成各种终端操作,如分组(groupingBy)、求和(summingInt)等。本文将详细介绍如何使用Stream API进行分组求和,并探讨如何处理BigDecimal类型的数值以及如何在分组求和后进行排序。

二、分组求和

首先介绍一下分组求和。分组求和是Stream API中一个常见的操作。以下是一个示例,展示如何根据拼团活动ID分组并计算每个活动的已拼团成功的总采购量。

代码语言:java复制
// 假设groupBuyBizService.selectList返回的是GroupBuyDO的List
List<GroupBuyDO> groupBuyList = groupBuyBizService.selectList(new EntityWrapper<GroupBuyDO>()
    .in("group_buy_activity_id", groupBuyActivityIds));

// 使用Stream API进行分组求和
Map<Long, Integer> purchasedNumbers = groupBuyList.stream()
    .filter(g -> SUCCEED.equals(g.getStatus())) // 过滤出已拼团成功的记录
    .collect(Collectors.groupingBy(GroupBuyDO::getGroupBuyActivityId, // 按拼团活动ID分组
        Collectors.summingInt(GroupBuyDO::getTotalPurchasedNumber))); // 对每个组的totalPurchasedNumber进行求和

三、处理BigDecimal类型的数值

这个案例主要是分析特殊场景,比如BigDecimal类型求和的情况。当需要处理BigDecimal类型的数值时,由于Stream API没有直接提供对BigDecimal的求和收集器,我们需要自行转换并求和。

代码语言:java复制
// 假设inventoryBizService.selectList返回的是ActivityProductInventoryDO的List
List<ActivityProductInventoryDO> inventoryList = inventoryBizService.selectList(new EntityWrapper<ActivityProductInventoryDO>()
    .in("activity_product_code", actProductCodes));

// 使用Stream API进行分组求和,但需要先转换BigDecimal为int(注意这可能会导致精度损失)
Map<String, Integer> inventoryValues = inventoryList.stream()
    .collect(Collectors.groupingBy(ActivityProductInventoryDO::getActivityProductCode,
        Collectors.summingInt(p -> p.getInventoryValue().setScale(0, RoundingMode.HALF_UP).intValue()))); // 假设inventoryValue为BigDecimal类型,并转换为int进行求和

// 如果需要保留BigDecimal的精度,可以使用自定义的收集器

四、分组求和后的排序

在分组求和后,如果需要按照某个键进行排序,可以使用TreeMap作为分组的结果容器。以下是一个示例,展示如何按照更新时间对金额历史记录进行分组求和,并排序。

代码语言:java复制
// 假设amountHistories是一个FlowAdAccountAmountHistory对象的List
List<FlowAdAccountAmountHistory> amountHistories = ...;

// 使用Stream API进行分组求和,并排序
TreeMap<Date, Integer> sortBalances = amountHistories.stream()
    .sorted(Comparator.comparing(FlowAdAccountAmountHistory::getUpdateTime, Comparator.nullsLast(Comparator.reverseOrder()))) // 先按更新时间降序排序
    .collect(Collectors.groupingBy(FlowAdAccountAmountHistory::getUpdateTime, // 分组
        TreeMap::new, // 使用TreeMap作为分组结果的容器以实现排序
        Collectors.summingInt(FlowAdAccountAmountHistory::getBalance))); // 对每个组的balance进行求和

五、总结

通过Java 8的Stream API,可以很方便地对数据集合进行分组求和操作。对于BigDecimal类型的数值,虽然Stream API没有直接提供对应的收集器,但可以通过自定义的转换逻辑来处理。同时本文也介绍了分组求和后,如果需要排序,可以使用TreeMap作为分组结果的容器。这些操作都体现了Java 8函数式编程的简洁和高效。在实际开发中,根据业务需求选择合适的收集器和排序方式,能够大大提高代码的可读性和可维护性。

我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

0 人点赞