本文正在参加「金石计划 . 分割6万现金大奖」

前语

嗨,大家好,我是希留,一个被迫致力于全栈开发的老菜鸟

近日项目里边有个新需求,一个列表原先是经过sql语句groupBy分组得到的集合。但现在因为事务需求变动,成果集的某个状况需要动态生成,再依据这个状况进行求和,所以就不能运用sql直接查询出成果,需要在程序里边处理。

例如下面的比如,这种集合分组操作首要想到的便是运用Stream的groupBy来处理,Stream的根本用法应该都知道吧,不会的能够移步【Java8新特性Stream的常见用法】了解一下。

因为是多字段分组,且还有依据不同条件求和,比较少用到。所以仍是值得记载一下,大家对于这种事务如果还有更优雅的完成方法,也请谈论区指点一下,感谢~

SQL语句的原型:

大约的事务便是:依据 learn_state 状况来判别相加course_credit字段的和 得到gainCredit,在判别gainCredit 是否大于等于moduleLowestCredit,得到state

SELECT
xrm.module_name moduleName,
xrm.module_lowest_credit moduleLowestCredit,
xrm.module_center_lowest_credit moduleCenterLowestCredit,
sum( CASE WHEN xsc.learn_state = '4' THEN xcm.course_credit ELSE 0 END ) gainCredit,
CASE WHEN sum( CASE WHEN xsc.learn_state = '4' THEN xcm.course_credit ELSE 0 END )>= xrm.module_lowest_credit
  THEN  '已满意结业条件' ELSE '未满意结业条件' END state
FROM
    table
WHERE
GROUP BY
  xrm.module_name,
  xrm.module_lowest_credit,
  xrm.module_center_lowest_credit

经过Stream完成

经过程序完成就需要把原先sql分组的数据都查询出来,不进行分组。如下比如:

得到所有待分组的数据,经过 stream 进行分组 。

    @Test
    public void testStreamGroupBySum(){
        // 要分组的数据
        List<Map<String, Object>> courseDetail = new ArrayList<>();
        Map<String, Object> testMap1 = new HashMap<>();
        testMap1.put("moduleName", "公共基础课");
        testMap1.put("moduleLowestCredit", "7");
        testMap1.put("moduleCenterLowestCredit", "7");
        testMap1.put("gainCredit", "3");
        testMap1.put("learnState", "1");
        courseDetail.add(testMap1);
        Map<String, Object> testMap2 = new HashMap<>();
        testMap2.put("moduleName", "公共基础课");
        testMap2.put("moduleLowestCredit", "7");
        testMap2.put("moduleCenterLowestCredit", "7");
        testMap2.put("gainCredit", "3");
        testMap2.put("learnState", "4");
        courseDetail.add(testMap2);
        Map<String, Object> testMap3 = new HashMap<>();
        testMap3.put("moduleName", "公共英语课");
        testMap3.put("moduleLowestCredit", "4");
        testMap3.put("moduleCenterLowestCredit", "3");
        testMap3.put("gainCredit", "4");
        testMap3.put("learnState", "4");
        courseDetail.add(testMap3);
        Map<String, Object> testMap4 = new HashMap<>();
        testMap4.put("moduleName", "公共英语课");
        testMap4.put("moduleLowestCredit", "4");
        testMap4.put("moduleCenterLowestCredit", "3");
        testMap4.put("gainCredit", "2");
        testMap4.put("learnState", "4");
        courseDetail.add(testMap4);
       // 多个字段分组计算处理
        Map<String, List<Map<String, Object>>> collectMap = courseDetail.stream().collect(Collectors.groupingBy(d ->
                d.get("moduleName") + "_" +
                        d.get("moduleLowestCredit")+ "_" +
                        d.get("moduleCenterLowestCredit"),Collectors.toList()));
        // 得到分组后的集合
        List<Map<String, Object>> newCourseDetail = collectMap.keySet().stream().map(key -> {
            Map<String, Object>  pointMap = new HashMap<>();
            String[] temp = key.split("_");
            pointMap.put("moduleName", temp[0]);
            pointMap.put("moduleLowestCredit", temp[1]);
            pointMap.put("moduleCenterLowestCredit", temp[2]);
            List<Map<String, Object>> collectList = collectMap.get(key);
            if (CollectionUtil.isNotEmpty(collectList)) {
                int tempCredit = 0;
                for (Map<String, Object> map : collectList) {
                    // 当条件是4时,相加分数
                    if ("4".equals(String.valueOf(map.get("learnState"))) && StrUtil.isNotBlank(String.valueOf(map.get("gainCredit")))) {
                        tempCredit += Integer.parseInt(String.valueOf(map.get("gainCredit")));
                    }
                }
                pointMap.put("gainCredit", tempCredit);
                pointMap.put("state", tempCredit >= Integer.parseInt(temp[1]) ? "已满意结业条件" : "未满意结业条件");
            }
            return pointMap;
        }).collect(Collectors.toList());
        System.out.print(courseDetail);
        System.out.print(newCourseDetail);
    }

输出成果

从输出的成果能够看出,已经得到了和原先sql共同的的成果集了。

courseDetail: [{
	moduleLowestCredit = 7,
	gainCredit = 3,
	moduleName = 公共基础课,
	learnState = 1,
	moduleCenterLowestCredit = 7
}, {
	moduleLowestCredit = 7,
	gainCredit = 3,
	moduleName = 公共基础课,
	learnState = 4,
	moduleCenterLowestCredit = 7
}, {
	moduleLowestCredit = 4,
	gainCredit = 4,
	moduleName = 公共英语课,
	learnState = 4,
	moduleCenterLowestCredit = 3
}, {
	moduleLowestCredit = 4,
	gainCredit = 2,
	moduleName = 公共英语课,
	learnState = 4,
	moduleCenterLowestCredit = 3
}]
newCourseDetail: [{
	moduleLowestCredit = 4,
	gainCredit = 6,
	moduleName = 公共英语课,
	state = 已满意结业条件,
	moduleCenterLowestCredit = 3
}, {
	moduleLowestCredit = 7,
	gainCredit = 3,
	moduleName = 公共基础课,
	state = 未满意结业条件,
	moduleCenterLowestCredit = 7
}]

总结

好了,以上便是本文的全部内容了,感谢大家的阅览。

本文经过一次实践项目事例,记载了运用 stream的多字段groupBy 来完成类似 mysql 中 sum、case when groupBy分组等语法。

如果有什么疑问或许主张,欢迎谈论区留下你的独到见解~