java8使用stream流的groupingBy归约函数分组后对分组中的对象进行二次处理

问题阐述

假设存在对象学生,学生中有主键,姓名,学生班级编码三个属性,如下:

@Data
public class Student{
    private Long studentId;
    private String studentName;
    private String studentClazzCode;
    private String studentClazzName;
}

对以上对象我们有以下几点说明:

  1. 主键[ studentId ]唯一
  2. 学生班级编码[ studentClazzCode ]为关联外键值,关联班级信息。为更好的说明问题我们假设以下班级信息,并且仅有以下班级信息:1[班级一];2[班级二];3[班级三]
  3. 学生班级名称[ studentClazzName ]为冗余值,为了方便辨认班级

让我们假设几条学生数据

public class test{

    private static final List<Student> studentList = new ArrayList();

    static{
        studentList.add(newStudent(1L,"张三","1","班级一"));
        studentList.add(newStudent(2L,"张四","1","班级一"));
        studentList.add(newStudent(3L,"张五","2","班级二"));
        studentList.add(newStudent(4L,"张六","2","班级二"));
        studentList.add(newStudent(5L,"张七","3","班级三"));
        studentList.add(newStudent(6L,"张八","3","班级三"));
    }

    private static Student newStudent(Long studentId,String studentName,String studentClazzCode,String studentClazzName){
        Student student = new Student();
        student.setStudentId(studentId);
        student.setStudentName(studentName);
        student.setStudentClazzCode(studentClazzCode);
        student.setStudentClazzName(studentClazzName);
        return student;
    }
}

现在需要将学生按照班级编码分组并且每个分组是一个学生主键的列表。

简单的流分组可以将学生按照班级编码分组,但是每个分组内是一个学生的信息列表,如下:

Map<String,List<Student>> result = studentList.stream().collect(Collectors.groupingBy(Student::getStudentClazzCode);

解决问题方案

很明显,这需要在分组之后进行一次map操作,将学生信息转换为学生主键信息[及把Student转换为Long主键],这需要在分组之后进一步操作,当然也可以将Map中的每个列表取出来,在当前列表适用stream的map操作,如下:

result.get("1").stream().map(Student::getStudentId).collect(Collectors.toList());

但是这样会增加多一步操作,不管是在代码编写的简洁性和出于性能的考虑都不太合适,于是考虑groupingBy操作中有没有对结果进行后续处理的操作,找出了Collectors.mapping()函数,查阅源码发现它的方法签名如下:

public static <T, U, A, R>
    Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
                               Collector<? super U, A, R> downstream);

方法存在两个参数:

  • 参数1:mapper 这是对对象进行转换的函数,在这里你可以自定义对对象的转换,此处我们需要在Student中取出Long型主键
  • 参数2: downstream 这是对处理结果的规约处理,在这里你可以对转换后的所有对象进行规约处理,此处我们需要把各个Long型主键规约成一个List集合

使用mapping()函数,我们可以吧代码简化成下面的:

Map<String,List<Long>> result = studentList.stream().collect(Collectors.groupingBy(Student::getStudentClazzCode,Collectors.mapping(Student::getStudentId,Collectors.toList()));

ok,最终的解决方案就是这样的,这种方式可以看到代码简洁到一行,不用再针对每个键值再对列表进行处理,而且由于流是Java内置的,所以在性能方面Java会对其进行优化

注意:代码并没有进行测试,在使用时请慎重

原文章地址请点击此处链接

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 8引入了Stream API,它是一种新的处理集合的方式,可以用更简洁、更易读的代码处理集合数据。Stream API提供了非常方便的、高效的数据处理方式,包括筛选、排序、映射、归约等。 下面是一些Stream的常用操作: 1. filter():筛选符合条件的元素 ```java List<String> list = Arrays.asList("apple", "orange", "banana", "pear", "peach"); List<String> result = list.stream().filter(str -> str.contains("e")).collect(Collectors.toList()); ``` 2. map():将元素转换成其他形式或提取信息 ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); List<Integer> result = nums.stream().map(num -> num * num).collect(Collectors.toList()); ``` 3. sorted():对元素进行排序 ```java List<Integer> nums = Arrays.asList(5, 3, 1, 2, 4); List<Integer> result = nums.stream().sorted().collect(Collectors.toList()); ``` 4. distinct():去重 ```java List<Integer> nums = Arrays.asList(1, 2, 3, 3, 4, 4, 5); List<Integer> result = nums.stream().distinct().collect(Collectors.toList()); ``` 5. limit():截取前n个元素 ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); List<Integer> result = nums.stream().limit(3).collect(Collectors.toList()); ``` 6. skip():跳过前n个元素 ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); List<Integer> result = nums.stream().skip(3).collect(Collectors.toList()); ``` 7. reduce():将元素归约为一个值 ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); int result = nums.stream().reduce(0, (a, b) -> a + b); ``` 这些操作只是Stream API的一部分,还有很多其他操作可以使用Stream API可以让我们更加方便地处理集合数据,提高开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值