Stream做分组并 根据条件 求 数据聚合

业务需求如下

在这里插入图片描述

逻辑

根据姓名先进行分组,然后针对分组后的数据,进行过滤,过滤出不同学科的数据集然后求它们的分数之和返回就是该同学的该科总成绩了

import com.sun.org.apache.regexp.internal.RE;

import java.sql.SQLOutput;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author wfw
 * @Date 2021/6/17  11:27
 */
public class StartTest {
    public static void main(String[] args) {
        List<Student> list=new ArrayList<Student>();
        list.add(new Student("张三","语文",80, LocalDateTime.now()));
        list.add(new Student("张三","数学",70, LocalDateTime.now()));
        list.add(new Student("李四","语文",60, LocalDateTime.now()));
        list.add(new Student("张三","英语",50, LocalDateTime.now()));
        list.add(new Student("李四","数学",70, LocalDateTime.now()));
        list.add(new Student("李四","英语",40, LocalDateTime.now()));
        list.add(new Student("张三","语文",80, LocalDateTime.now()));
        list.add(new Student("张三","数学",70, LocalDateTime.now()));
        list.add(new Student("张三","英语",50, LocalDateTime.now()));
        System.out.println("列表打印:");
        list.forEach(c->{
            System.out.println(c);
        });
        Map<String, Map<String, Object>> okmap = list.stream().collect(Collectors.groupingBy(Student::getName, Collectors.collectingAndThen(Collectors.toList(), m -> {
            Map<String, Object> retMap = new HashMap<>();
            int yw = m.stream().filter(mm -> mm.getXueKe().equals("语文")).mapToInt(mmm -> Integer.valueOf(mmm.getScore())).sum();
            int sx = m.stream().filter(mm -> mm.getXueKe().equals("数学")).mapToInt(mmm -> Integer.valueOf(mmm.getScore())).sum();
            int yy = m.stream().filter(mm -> mm.getXueKe().equals("英语")).mapToInt(mmm -> Integer.valueOf(mmm.getScore())).sum();
            retMap.put("yws", yw);
            retMap.put("sxs", sx);
            retMap.put("yys", yy);
            return retMap;
        })));

        System.out.println("计算后");

        System.out.println(okmap);


    }
}

打印后的结果

在这里插入图片描述

### Java 8 Stream 流的分组与排序 #### 对流数据进行分组操作 在处理复杂的数据集时,`groupingBy` 是一种强大的工具。此功能允许基于特定属性对元素进行分类。对于多字段分组的情况,可以嵌套 `Collectors.groupingBy()` 方法来实现更复杂的逻辑。 例如,在员工对象列表中按部门和职位级别两个维度来进行统计: ```java Map<Department, Map<PositionLevel, List<Employee>>> result = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.groupingBy(Employee::getPositionLevel))); ``` 这段代码首先按照 `Employee.getDepartment()` 的返回值作为外层键值进行第一次分组;接着针对每一个部门内部的结果再次调用 `groupingBy` 函数依据 `Employee.getPositionLevel()` 完成二次划分[^1]。 #### 实现分组后的汇总计算 除了简单的收集到 map 结构中外,还可以结合其他 collector 来完成诸如计数、和等聚合运算。比如要获取各部门各职级下的薪资总额,则可以在上述基础上追加 summingInt 或者 summarizingLong 收集器: ```java Map<String, Map<Integer, Integer>> salarySummaries = employeeList.stream().collect( Collectors.groupingBy(Employee::getDepartment, Collectors.groupingBy(Employee::getPositionLevel, Collectors.summingInt(Employee::getSalary)))); ``` 这里展示了如何通过链式调用来构建一个多级映射表结构,最终得到每一对 (department, position_level) 关联起来的所有雇员工资总和的信息。 #### 添加排序机制 当需要对已有的分组结果进一步排列时,可借助于 TreeMap 构造函数或 sorted() 中间操作符达成目的。如果希望整个输出保持有序状态,那么应该考虑使用 TreeMap 替代 HashMap 存储中间结果: ```java Comparator<Map.Entry<K,V>> comparator = ... ;// 自定义比较器 TreeMap<K,List<V>> collect = list.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1,v2)->{throw new RuntimeException("Duplicate keys!");}, ()->new TreeMap<>(comparator))); ``` 另一种方案是在流水线末端加入 sorting 步骤,这适用于那些不改变原有 key-value 映射关系而仅调整其遍历顺序的情形下: ```java employeeList.stream() .sorted((e1,e2)-> e1.getName().compareTo(e2.getName())) ... ``` 或者直接指定 Comparator 参数给 sort 方法简化表达: ```java employees.stream() .sorted(comparing(Employee::getName)) ... ``` 综上所述,通过对 Stream API 合理运用以及 Collector 工具类的支持,能够轻松地完成从原始集合向具有层次化特征的新容器转换的过程,同时也能灵活控制其中元素呈现出来的先后次序[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值