JAVA Stream的collect用法与原理(详解)

本文详细介绍了Java Stream的collect方法及Collector接口,通过实例展示了如何使用collect进行数据收集、分组、归约和嵌套操作。讲解了Collectors工具类提供的常见收集器,并探讨了如何开发自定义收集器,帮助提升开发效率。
摘要由CSDN通过智能技术生成

初识Collector
先看一个简单的场景:
现有集团内所有人员列表,需要从中筛选出上海子公司的全部人员

假定人员信息数据如下:

姓名 子公司 部门 年龄 工资
大壮 上海公司 研发一部 28 3000
二牛 上海公司 研发一部 24 2000
铁柱 上海公司 研发二部 34 5000
翠花 南京公司 测试一部 27 3000
玲玲 南京公司 测试二部 31 4000

如果你曾经用过Stream流,或者你看过我前面关于Stream用法介绍的文章,那么借助Stream可以很轻松的实现上述诉求:

public void filterEmployeesByCompany() {
    List<Employee> employees = getAllEmployees().stream()
            .filter(employee -> "上海公司".equals(employee.getSubCompany()))
            .collect(Collectors.toList());
    System.out.println(employees);
}


上述代码中,先创建流,然后通过一系列中间流操作(filter方法)进行业务层面的处理,然后经由终止操作(collect方法)将处理后的结果输出为List对象。


但我们实际面对的需求场景中,往往会有一些更复杂的诉求,比如说:

现有集团内所有人员列表,需要从中筛选出上海子公司的全部人员,并按照部门进行分组


其实也就是加了个新的分组诉求,那就是先按照前面的代码实现逻辑基础上,再对结果进行分组处理就好咯:

public void filterEmployeesThenGroup() {
    // 先 筛选
    List<Employee> employees = getAllEmployees().stream()
            .filter(employee -> "上海公司".equals(employee.getSubCompany()))
            .collect(Collectors.toList());
    // 再 分组
    Map<String, List<Employee>> resultMap = new HashMap<>();
    for (Employee employee : employees) {
        List<Employee> groupList = resultMap
                .computeIfAbsent(employee.getDepartment(), k -> new ArrayList<>());
        groupList.add(employee);
    }
    System.out.println(resultMap);
}


似乎也没啥毛病,相信很多同学实际编码中也是这么处理的。但其实我们也可以使用Stream操作直接完成:

public void filterEmployeesThenGroupByStream() {
    Map<String, List<Employee>> resultMap = getAllEmployees().stream()
            .filter(employee -> "上海公司".equals(employee.getSubCompany()))
            .collect(Collectors.groupingBy(Employee::getDepartment));
    System.out.println(resultMap);
}


两种写法都可以得到相同的结果:

{
    研发二部=[Employee(subCompany=上海公司, department=研发二部, name=铁柱, age=34, salary=5000)], 
    研发一部=[Employee(subCompany=上海公司, department=研发一部, name=大壮, age=28, salary=3000),              Employee(subCompany=上海公司, department=研发一部, name=二牛, age=24, salary=2000)]
}


上述2种写法相比而言,第二种是不是代码上要简洁很多?而且是不是有种自注释的味道了?
通过collect方法的合理恰当利用,可以让Stream适应更多实际的使用场景,大大的提升我们的开发编码效率。下面就一起来全面认识下collect、解锁更多高级操作吧。


collect\Collector\Collectors区别与关联


刚接触Stream收集器的时候,很多同学都会被collect,Collector,Collectors这几个概念搞的晕头转向,甚至还有很多人即使已经使用Stream好多年,也只是知道collect里面需要传入类似Collectors.toList()这种简单的用法,对其背后的细节也不甚了解。


这里以一个collect收集器最简单的使用场景来剖析说明下其中的关系:


概括来说

1️  collect是Stream流的一个 终止方法,会使用传入的收集器(入参)对结果执行相关的操作,这个收集器必须是Collector接口的某个具体实现类
2️  Collector是一个 接口,collect方法的收集器是Collector接口的 具体实现类
3️  Collectors是一个 工具类,提供了很多的静态工厂方法, 提供了很多Collector接口的具体实现类,是为了方便程序员使用而预置的一些较为通用的收集器(如果不使用Collectors类,而是自己去实现Collector接口,也可以)。
 


Collector使用与剖析


到这里我们可以看出,Stream结果收集操作的本质,其实就是将Stream中的元素通过收集器定义的函数处理逻辑进行加工,然后输出加工后的结果


根据其执行的操作类型来划

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值