2、数据源的获取
2.1、数据源的简介
数据源,顾名思义,既是流中的数据的来源。是集合的流式编程的第一步,将数据源中的数据读取到流中,进行处理。注意:将数据读取到流中进行处理的时候,与数据源中的数据没有关系。也就是说,中间操作对流中的数据进行处理、过滤、映射、排序...,此时是不会影响数据源中的数据的。
2.2、数据源的获取
这个过程,其实是将一个容器中的数据,读取到一个流中。因此无论什么容器作为数据源,读取到流中的方法返回值一定是一个Stream。
// 1、通过Collection接口中的stream()方法获取数据源为Collection的流Stream stream = list.stream();
// 2、通过Collection接口的parallelStream()方法获取数据源为Collection的流Stream stream = list.parallelStream();
// 3、通过Arrays工具类中的stream()方法获取数据源为数组的流IntStream stream = Arrays.stream(array);关于stream()和parallelStream
他们都是Collection集合获取数据源的方法,不同点在于stream()方法获取的数据源是串行的,parallelStream()获取的数据源是并行的。parallelStream()内部集成了多个线程对流中的数据进行操作,效率更高。
3、最终操作
3.1、最终操作的简介
将流中的数据整合到一起,可以存入一个集合,也可以直接对流中的数据进行遍历、数据统计...,通过最终操作,需要掌握如何从流中提取出来我们想要的信息。
注意事项:最终操作,之所以叫最终操作,是因为,在最终操作执行结束后,会关闭这个流,流中的所有数据都会销毁。如果使用一个已经关闭了的流,会出现异常。
3.2、collect
将流中的数据收集到一起,对这些数据进行一些处理。最常见的处理,就是将流中的数据存入一个集合。collect方法的参数,是一个Collector接口,而且这个接口并不是一个函数式接口。实现这个接口,可以自定义收集的规则。但是,绝大部分情况下,不需要自定义。
直接使用 Collectors 工具类提供的方法即可。
// 1.1、转成 ListList result1 = list.stream().collect(Collectors.toList());
System.out.println(result1);
// 1.2、转成 SetSet result2 = list.stream().collect(Collectors.toSet());
System.out.println(result2);
// 1.3、转成 Map,提供两个函数式接口的实现,分别实现键的生成规则和值的生成规则Map result3 = list.stream().collect(Collectors.toMap(ele -> ele / 10, ele -> ele));
System.out.println(result3);
3.3、reduce
将流中的数据按照一定的规则聚合起来。
// 将流的元素,逐一带入到这个方法中,进行运算// 最终的运算结果,得到的其实是一个 Optional 类型,需要使用 get() 获取到里面的数据int result4 = list.stream().reduce((e1, e2) -> e1 + e2).get();
System.out.println(result4);
3.4、count
统计流中的元素数量。
long result5 = list.stream().count();
System.out.println(result5);
3.5、forEach
迭代、遍历流中的数据。
list.stream().forEach(System.out::println);
3.6、max & min
获取流中的最大的元素、最小的元素。
// 获取最大值Integer result6 = list.stream().max(Integer::compareTo).get();
System.out.println("max is : " + result6);
// 获取最小值Integer result7 = list.stream().min(Integer::compareTo).get();
System.out.println("min is : " + result7);
3.7、Matching
allMatch: 只有当流中所有的元素,都匹配指定的规则,才会返回 true
anyMatch: 只要流中有任意的数据,满足指定的规则,都会返回 true
noneMatch: 只有当流中的所有的元素,都不满足指定的规则,才会返回true
// 判断流中是否所有的元素都大于 50boolean result8 = list.stream().allMatch(ele -> ele > 50);
System.out.println(result8);
// 判断流中是否有大于 50 的数据boolean result9 = list.stream().anyMatch(ele -> ele > 50);
System.out.println(result9);
// 判断流中是否没有奇数boolean result10 = list.stream().noneMatch(ele -> ele % 2 != 0);
System.out.println(result10);
3.8、find
findFirst: 从流中获取一个元素(一般情况下,是获取的开头的元素)
findAny: 从流中获取一个元素(一般情况下,是获取的开头的元素)
这两个方法,绝大部分情况下,是完全相同的,但是在多线程的环境下,findAny和find返回的结果可能不一样。
Integer result11 = list.parallelStream().findFirst().get();
System.out.println(result11);
Integer result12 = list.parallelStream().findAny().get();
System.out.println(result12);
3.9、最终操作的注意事项
最终操作,会关闭流。如果一个流被关闭了,再去使用这个流,就出出现异常。
// 9、最终操作错误示范Stream stream = list.stream();
long count = stream.count();
stream.forEach(System.out::println);
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at com.qf.cstream.FinalOperationDemo.main(FinalOperationDemo.java:78)