代码
package com.kabka.test;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* List 分组求和
*
* @author yunnuo
* @since 2022-06-11
*/
@Slf4j
public class ListGroupSumTest {
@Test
public void testSum() {
List<Map<String, Object>> mapList = new ArrayList<>();
String[] names = {"张三", "李四", "王五"};
// 循环mock 随机值
for (int i = 0; i < 10; i++) {
Map<String, Object> map = new HashMap<>();
map.put("name", names[new Random().nextInt(3)]);
map.put("value", i);
map.put("money", new BigDecimal(new Random().nextFloat() * i).setScale(4, BigDecimal.ROUND_DOWN));
mapList.add(map);
}
log.info("原始未分组mapList:{}", JSONUtil.toJsonStr(mapList));
// 通过name进行分组
Map<String, List<Map<String, Object>>> mapListGroupByName = mapList.stream().collect(Collectors.groupingBy(map -> map.get("name").toString()));
log.info("分组后:{}", JSONUtil.toJsonStr(mapListGroupByName));
List<Map<String, Object>> groupMapList = new ArrayList<>();
// 对分组数据进行求和操作
mapListGroupByName.forEach((name, mapByNameList) -> {
HashMap<String, Object> reMap = new HashMap<>();
// 求和
int sum = mapByNameList.stream().mapToInt(map -> Integer.parseInt(map.get("value").toString())).sum();
// 最大值
OptionalInt maxOpt = mapByNameList.stream().mapToInt(map -> Integer.parseInt(map.get("value").toString())).max();
// 最小值
Long count = mapByNameList.stream().mapToInt(map -> Integer.parseInt(map.get("value").toString())).count();
// 平均值
OptionalDouble averageOpt = mapByNameList.stream().mapToInt(map -> Integer.parseInt(map.get("value").toString())).average();
BigDecimal sumMoney = new BigDecimal(0);
// BigDecimal 进行 求和
for (Map<String, Object> map : mapByNameList) {
BigDecimal money = new BigDecimal(map.get("money").toString());
sumMoney= sumMoney.add(money);
}
reMap.put("name", name);
reMap.put("sum", sum);
reMap.put("count", count);
reMap.put("sumMoney", sumMoney);
maxOpt.ifPresent(max -> reMap.put("max", max));
averageOpt.ifPresent(average -> reMap.put("average", average));
groupMapList.add(reMap);
});
log.info("分组后聚合List:{}", JSONUtil.toJsonStr(groupMapList));
}
}
解析
本博主采用map来代替DTO
,进行对map对象->mapList
循环随机赋值,属性分别为:name、value、money
然后对mapList 通过name
属性进行分组 生成新的map为 mapListGroupByName
,其中生成的map的key是采用分组的name作为key,相同name的map则放在一起生成mapListGroupByName的value值 :List<Map<String, Object>>
,从下图可看出
其中分组李四有两条数据,张三有五条, 王五有三条
后面我们将分组后的map:mapListGroupByName
进行聚合操作:求和、平均值、最大值、最小值和BigDecimal求和形成一个新的 List<Map<String, Object>>
对象groupMapList,如下图所示
其中Java8新特性中的stream操作可以对数据进行直接求和、平均值、最大值、最小值等,感兴趣的小伙伴可以自行看api,博主这边还对BigDecimal类型的数据进行求和了,所以一般涉及到金钱等重要数据采用BigDecimal来存储的话,也可以像博主一样进行循环求和操作。
// 求和
int sum = mapByNameList.stream().mapToInt(map -> Integer.parseInt(map.get("value").toString())).sum();
// 最大值
OptionalInt maxOpt = mapByNameList.stream().mapToInt(map -> Integer.parseInt(map.get("value").toString())).max();
// 最小值
Long count = mapByNameList.stream().mapToInt(map -> Integer.parseInt(map.get("value").toString())).count();
// 平均值
OptionalDouble averageOpt = mapByNameList.stream().mapToInt(map -> Integer.parseInt(map.get("value").toString())).average();
BigDecimal sumMoney = new BigDecimal(0);
// BigDecimal 进行 求和
for (Map<String, Object> map : mapByNameList) {
BigDecimal money = new BigDecimal(map.get("money").toString());
sumMoney= sumMoney.add(money);
}
版权声明:程序员胖胖胖虎阿 发表于 2022年11月21日 上午5:48。
转载请注明:Java stream对List对象进行分组聚合操作:求和、平均值、最大值、最小值,BigDecimal求和 | 胖虎的工具箱-编程导航
转载请注明:Java stream对List对象进行分组聚合操作:求和、平均值、最大值、最小值,BigDecimal求和 | 胖虎的工具箱-编程导航
相关文章
暂无评论...