声明:本篇文章除部分引用外,均为原创内容,如有雷同纯属巧合,引用转载请附上原文链接与声明
本文链接:
注:阅读本篇文章需掌握java集合基础知识、Stream基本语法与使用、函数式接口、lambda表达式、泛型知识、lombok插件使用、guava基础集合工具使用、java8双冒号的使用;请先掌握上述知识再行阅读本篇文章。若有错误,欢迎友好纠正,谢谢。
参考引用
文章大纲
Stream基础收集功能演示
Stream收集原理分析
Collectors.toList()、Collectors.toMap()、Collectors.toSet()源码分析
Collectors.joining()源码分析
Collectors.reducing()源码分析
自定义Stream收集器演示
一、Stream基本收集功能演示
public void testStream() {
Student s1 = new Student(“s1”, 1, 20);
Student s2 = new Student(“s2”, 2, 24);
Student s3 = new Student(“s3”, 3, 26);
List students = Lists.newArrayList(s1, s2, s3);
List names = students.stream() // 将students Stream化处理
.filter(stu -> stu.getAge() > 23) // 只取年龄大于23的元素,即保留:s2,s3
.map(Student::getName) // 获取将Stream流中Student元素中的姓名组成新的Stream流
.collect(Collectors.toList()); // 将Stream流收集为List集合中
names.forEach(System.out::println); // names 进行挨个打印 结果为:s2 , s3
}
@Data
@AllArgsConstructor
public class Student {
private String name;// 姓名
private Integer stuNo; // 学号
private Integer age; // 年龄
}
在上述例子中,从结果的角度,该例是通过stream提供的api取得了students集合中的元素年龄大于23的姓名构成的新集合。从过程的角度主要分为以下几步:
将然后调用students.stream()将其转换为Stream流准备进行后续处理;
调用filter(Predicate predicate)将stream流中的元素进行过滤:仅保留age > 23的元素
调用map(Function mapper)将stream流中的元素进行包装:取得student的name取代原Stream流中的元素
调用collect(Collector collector)将Stream元素进行收集,按照传入的Collector规则进行收集:Collectors.toList()返回的Collector是将Stream流中的元素收集为List集合。
二、Stream收集原理分析
Collectors.toList()返回了一个已初始化完 成的Collector实例,查看Collectors.toList()方法,可以看到该方法实现如下:
public static Collector> toList() {
return new CollectorImpl<>((Supplier>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
可以看到该方法返回了一个CollectorImpl对象,CollectorImpl类是Collectors的静态内部类,实现了Collector接口。接下来再查看CollectorImpl类及其对应的构造方法,如下:
static class CollectorImpl implements Collector {
private final Supplier supplier;
private final BiConsumer accumulator;
pr