什么是stream
-
Stream 中⽂称为 “流”,通过将集合转换为这么⼀种叫做 “流”的元素队列,通过声明性⽅式,
-
能够对集合中的每个元素进⾏⼀系列并⾏或串⾏的流⽔线操作
-
元素是特定类型的对象,所以元素集合看作⼀种流, 流在管道中传输, 且可以在管道的节点上进⾏处理, ⽐如 排序,聚合,过滤等操作
-
操作详情
- 数据元素便是原始集合,如List、Set、Map等
- ⽣成流,可以是串⾏流stream() 或者并⾏流 parallelStream()
- 中间操作,可以是 排序,聚合,过滤,转换等
- 终端操作,很多流操作本身就会返回⼀个流,所以多个操作可以直接连接起来,最后统⼀进⾏收集
- 概览stream接⼝源码
-
map函数
将流中的每⼀个元素 T 映射为 R(类似类型转换)
上堂课的例⼦就是,类似遍历集合,对集合的每个对象做处理
场景:转换对象,如javaweb开发中集合⾥⾯的DO对象转换为DTO对象 -
filter函数
⽤于通过设置的条件过滤出元素
场景:主要⽤于筛选过滤出符合条件的元素 -
sorted函数
sorted() 对流进⾏⾃然排序, 其中的元素必须实现Comparable 接⼝
List<String> list = Arrays.asList("springboot", "springcloud",
"redis", "git", "netty", "java", "html", "docker");
List<String> resultList =
list.stream().sorted().collect(Collectors.toList());
- sorted(Comparator<? super T> comparator) ⽤来⾃定义升降序
List<String> list = Arrays.asList("springboot", "springcloud",
"redis", "git", "netty", "java", "html", "docker");
//根据⻓度进⾏排序
//List<String> resultList =
list.stream().sorted(Comparator.comparing(obj ->
obj.length())).collect(Collectors.toList());
//List<String> resultList =
list.stream().sorted(Comparator.comparing(obj ->
obj.length(),Comparator.reverseOrder())).collect(Collectors.toList()
);
//List<String> resultList =
list.stream().sorted(Comparator.comparing(String::length).reversed()
).collect(Collectors.toList());
System.out.println(resultList);
- limit函数
截断流使其最多只包含指定数量的元素
List<String> list = Arrays.asList("springboot", "springcloud",
"redis", "git", "netty", "java", "html", "docker");
//limit截取
List<String> resultList =
list.stream().sorted(Comparator.comparing(String::length).reversed()
).limit(3).collect(Collectors.toList());
System.out.println(resultList);
- allMatch函数
检查是否匹配所有元素,只有全部符合才返回true
List<String> list = Arrays.asList("springboot", "springcloud", "redis",
"git", "netty", "java", "html", "docker");
boolean flag = list.stream().allMatch(obj->obj.length()>1);
System.out.println(flag);
- anyMatch函数
检查是否⾄少匹配⼀个元素
List<String> list = Arrays.asList("springboot", "springcloud", "redis",
"git", "netty", "java", "html", "docker");
boolean flag = list.stream().anyMatch(obj->obj.length()>18);
System.out.println(flag);
- max和min函数
最⼤值和最⼩值
List<Student> list = Arrays.asList(new Student(32),new
Student(33),new Student(21),new Student(29),new Student(18));
//list.stream().max(Comparator.comparingInt(Student::getAge));
//最⼤
Optional<Student> optional = list.stream().max((s1, s2)-
>Integer.compare(s1.getAge(),s2.getAge()));
//最⼩
Optional<Student> optional = list.stream().min((s1, s2)-
>Integer.compare(s1.getAge(),s2.getAge()));
System.out.println(optional.get().getAge());
-
并⾏流parallelStream
-
为什么会有这个并⾏流
- 集合做重复的操作,如果使⽤串⾏执⾏会相当耗时,因此⼀般会采⽤多线程来加快, Java8的paralleStream⽤fork/join框架提供了并发执⾏能⼒
- 底层原理
线程池(ForkJoinPool)维护⼀个线程队列
可以分割任务,将⽗任务拆分成⼦任务,完全贴合分治思想
-
问题
- paralleStream并⾏是否⼀定⽐Stream串⾏快?
错误,数据量少的情况,可能串⾏更快,ForkJoin会耗性能 - 多数情况下并⾏⽐串⾏快,是否可以都⽤并⾏
不⾏,部分情况会有线程安全问题,parallelStream⾥⾯使⽤的外部变量,⽐如集合⼀定要使⽤线程安全集合,不然就会引发多线程安全问题
- paralleStream并⾏是否⼀定⽐Stream串⾏快?
-
reduce操作
- 常⽤⽅法⼀
Optional<T> reduce(BinaryOperator<T> accumulator);
- accumulator 计算的累加器
- 例⼦: 第⼀个元素相加和第⼆个元素相加,结果再和第三个元素相加,直到全部相加完成
int value = Stream.of(1, 2, 3, 4, 5).reduce((item1, item2) -> item1+ item2).get();
- 常⽤⽅法二
T reduce(T identity, BinaryOperator<T> accumulator);
- identity ⽤户提供⼀个循环计算的初始值
- accumulator 计算的累加器
- 例⼦: 100作为初始值,然后和第⼀个元素相加,结果在和第⼆个元素相加,直到全部相加完成
int value = Stream.of(1, 2, 3, 4,5).reduce(100, (sum, item) -> sum + item);
- forech
List<Student> results = Arrays.asList(new Student(32),new
Student(33),new Student(21),new Student(29),new Student(18));
results.forEach(obj->{
System.out.println(obj.toString());
});
- 注意事项
- 不能修改包含外部的变量的值
- 不能⽤break或者return或者continue等关键词结束或者跳过循环
collector收集器
- collect()⽅法的作⽤
- ⼀个终端操作, ⽤于对流中的数据进⾏归集操作,collect⽅法接受的参数是⼀个Collector
-
Collectors 的作⽤
⼯具类,提供了很多常⻅的收集器实现
Collectors.toList()
ArrayList::new,创建⼀个ArrayList作为累加器
List::add,对流中元素的操作就是直接添加到累加器中
reduce操作, 对⼦任务归集结果addAll,后⼀个⼦任务的结果直接全部添加到
前⼀个⼦任务结果中
CH_ID 是⼀个unmodifiableSet集合
Collectors.toMap()
Collectors.toSet()
Collectors.toCollection() :⽤⾃定义的实现Collection的数据结构收集
Collectors.toCollection(LinkedList::new)
Collectors.toCollection(CopyOnWriteArrayList::new)
Collectors.toCollection(TreeSet::new)
- joining函数
3种重载⽅法
Collectors.joining()
Collectors.joining("param")
Collectors.joining("param1", "param2", "param3")
-
说明:
该⽅法可以将Stream得到⼀个字符串, joining函数接受三个参数,分别表示 元素之间的连接符、前缀和后缀。 -
partitioningBy分组
-
练习: 根据list⾥⾯进⾏分组,字符串⻓度⼤于4的为⼀组,其他为另外⼀组
List<String> list = Arrays.asList("java", "springboot",
"HTML5","nodejs","CSS3");
Map<Boolean, List<String>> result =
list.stream().collect(partitioningBy(obj -> obj.length() > 4));
-
group by分组
todo 案例待补充 -
summarizingIn
todo 案例待补充