
前言
在最近的开发工作中经常用到Stream流来对list进行处理,相比于循环遍历,通过Stream流来处理list不但可以简化代码,而且能够提高系统性能,同时使得开发效率变得更高。本文就对Stream流进行简单的介绍。

Stream流简介
Stream是Java8新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选、排序、聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由终端操作 (terminaloperation) 得到前面处理的结果,它更专注于对数据源进行各种高效的聚合操作和大批量数据操作。
Stream的UML类图如下图所示:

Stream流的特性
Stream流主要包含以下3个特性:
Stream流不是一种数据结构,它本身并不保存数据,只是在原数据集上定义了一组操作。
这些定义的操作是惰性的,即每当访问到流中的一个元素,才会在此元素上执行这一系列操作。
由于Stream流不保存数据,因此每个Stream流只能使用一次。
在无状态操作中,在处理流中的元素时,会对当前的元素进行单独处理。比如,过滤操作,因为每个元素都是被单独进行处理的,所有它和流中的其它元素无关。
在有状态操作中,某个元素的处理可能依赖于其他元素。比如查找最小值,最大值,和排序,因为他们都依赖于其他的元素。

Stream流常用方法
如第二节中提到,Stream流的操作分为中间操作和终止操作,因此这两种操作也都对应着不同的方法,本节将主要介绍这两种操作的常用方法:
中间操作常用方法
filter():将结果为false的元素过滤掉
map():转换元素的值,可以用方法引用或者lambda表达式
flatMap():若元素是流,将流摊平为正常元素,再进行元素转
limit():保留前n个元素
skip():跳过前n个元素
distinct():剔除重复元素
sorted():将元素进行排序
List<Integer> num = Arrays.asList(2,4,8,1,0,5,7,1,3,6,9,5);
num.stream().filter(integer -> integer % 2 == 0) // 选出偶数
.distinct() // 去重
.sorted((a,b) -> b.compareTo(a)) // 排序
.forEach(a -> System.out.println(a + " ")); // 遍历输出
num.stream().limit(5) // 选出前5个元素
.forEach(System.out::println); //遍历输出
num.stream().skip(2) // 跳过前2个元素
.forEach(System.out::println); //遍历输出
num.stream().map(a -> a + 1) // 每个元素+1
.collect(Collectors.toList())
.forEach(System.out::println); //遍历输出
复制
约简操作
max():返回最大值元素
min():返回最小值元素
count():返回元素数量
findFirst():返回第一个元素
findAny():返回任意元素
anyMatch():任意元素匹配时返回true
allMatch():所有元素匹配时返回true
noneMatch():没有元素匹配时返回true
reduce():合并流中的元素
List<Integer> num = Arrays.asList(2,4,8,1,0,5,7,1,3,6,9,5);
long count =num.stream().filter(integer -> integer % 2 == 0)
.count(); // 选出偶数个数
System.out.println(num.stream().allMatch(a -> a >5)); //false
System.out.println(num.stream().anyMatch(a -> a >5)); //true
System.out.println(num.stream().noneMatch(a -> a >5)); //false
复制
forEach():对流中的每个元素进行操作
toArray():将流中的所有元素转换成为一个数组
List<Integer> num = Arrays.asList(2,4,8,1,0,5,7,1,3,6,9,5);
Integer[] nums = num.stream().toArray(Integer[] :: new); //list转换为数组
复制

小结