流式编程
简介
1.Stream是JDK1.8之后出现的新特性;
2.Stream是对集合操作的增强,流不是集合的元素,不是一种数据结构,不负责数据的存储的。流更像是 一个迭代器,可以单向的遍历一个集合中的每一个元素,并且不可循环。
目的
有时候,对集合中的元素进行操作时,需要使用到其他操作的结果。
在这个过程中,集合的流式编程可以大幅度的简化代码的数量。
将数据源中的数据,读取到一个流中,可以对这个流中的数据进行操作(删除、过滤、映射等)。每次的操作结果也是一个流对象,可以对这个流再进行其他的操作。
使用流式编程的步骤
1.获取数据源,将数据源中的数据读取到流中。
2.对流中的数据进行各种各样的处理。
3.对流中的数据进行整合处理。
过程2中,有若干方法,可以对流中的数据进行各种各样的操作,并且返回流对象本身,这样的操作被称为中间操作。
过程3中,有若干方法,可以对流中的数据进行各种处理,并关闭流,这样的操作被称为最终操作。
在中间操作和最终操作中,基本上所有的方法参数都是函数式接口,可以使用lambda表达式来实现。
数据源
介绍
数据源:就是流中的数据的来源。是集合的流式编程的第一步,将数据源中的数据读取到流 中,进行处理。
注意:将数据读取到流中进行处理的时候,与数据源中的数据没有关系。也就是说,中间操作对流中的数据进行处理、过滤、映射、排序... ,此时是不会影响数据源中的数据的
数据源的获取
这个过程,其实是将一个容器中的数据,读取到一个流中。因此无论什么容器作为数据源,读取到流中的方法返回值一定是一个Stream。
//通过集合获取到流对象是串行的
Stream<Integer> stream = list.stream();
//通过集合获取到流对象是并行的
Stream<Integer> stream = list.parallelStream();
//获取数据源为数组的流
IntStream stream = Arrays.stream(array);
最终操作
1.将流中的数据整合到一起,可以存入一个集合,也可以直接对流中的数据进行遍历、数据统计...
2.在最终操作执行结束后,会关闭这个流,流中的所有数据都会销毁。如果使用一个已经关闭了的流,会出现异常。
collect
1.将流中的数据收集到一起,对这些数据进行一些处理。
2.最常见的处理,就是将流中的数据存入一个集合。
3.collect方法的参数,是一个Collector接口,而且这个接口并不是一个函数式接口。实现这个接口, 可以自定义收集的规则。但是,绝大部分情况下,不需要自定义,直接使用Collectors工具类提供的方法即可
//转成List集合
List<Integer> r1 = list.stream().collect(Collectors.toList());
System.out.println(r1);
//转成Set集合
Set<Integer> r2 = list.stream().collect(Collectors.toSet());
System.out.println(r2);
//转成Map集合
Map<Integer,Integer> r3 = list.stream().collect(Collectors.toMap(ele ->ele/10,ele->ele));
System.out.println(r3);
reduce
将流中的数据按照一定的规则聚合起来。
返回的类型:Optional,需要调用它的get方法,获取里面的数据
Optional<Integer> reduce = list.stream().reduce(a,b)->(a - b));
int r = reduce.get();
count
统计流中的元素数量。
long sum = list.stream().count();
System.out.println(sum);
forEach
迭代、遍历流中的数据。
list.stream().forEach(System.out::println);
max、min
获取流中的最大的元素、最小的元素。
max(Comparator c):
获取排序后的最后一个元素min(Comparator c):
获取排序后的第一个元素
int a = list.stream().max((a,b)->a-b).get();
int b = list.stream().min((a,b)->a-b).get();
Matching
allMatch: 只有当流中所有的元素,都匹配指定的规则,才会返回 true
anyMatch: 只要流中有任意的数据,满足指定的规则,就会返回 true
noneMatch: 只有当流中的所有的元素,都不满足指定的规则,才会返回true
boolean a = list.stream().allMatch(e->e<10);
boolean b = list.stream().anyMatch(e->e<2);
boolean c = list.stream().noneMatch(e->e<0);
find
findFirst: 从流中获取一个元素
findAny: 从流中获取一个元素
针对于串行的流,获取的都是第一个元素
针对于并行的流,获取的元素应该不同
int a = list.stream().findFirst().get();
int b = list.stream().findAny().get();
中间操作
filter
过滤出来满足条件的数据
//要集合中的所有的奇数
List<Integer> c = list.stream().filter(x -> x%2!=0).collect(Collectors.toList());
distinct
distinct() 去重
list.stream().distinct().forEach(System.out::println);
sorted
sorted():排序
sorted(Comparator c): 自定义比较规则
list.stream().sorted((a,b)->b-a).forEach(System.out::println);
limit、skip
limit(long size): 表示截取流中的前size个元素
skip(long size): 表示跳过前size个元素
list.stream().limit(3).forEach(System.out::println);
list.stream().skip(2).forEach(System.out::println);
map
将元素映射成另外一种类型
list.stream().map(e->""+e).collect(Collectors.toList());//映射成字符串类型
mapToInt
mapToInt(....): 将元素映射成intStream
mapToLong(....): 将元素映射成longStream
mapToDouble(....): 将元素映射成doubleStream
int sum = list.stream().mapToInt(e->1).sum();