这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
阅读《Java实战》,本文为第5章总结,主要系统全面的介绍Steam的API,包含筛选、切片和映射,查找与匹配、归约操作、数值流、以及流的各种构建方法。
1、筛选
从流中筛选出目标对象,主要分为两个:
- filter(Predicate):基于谓词(返回boolean的函数式接口)筛选过滤
- distinct() : 筛选去重
- limit(n) :截断流,即返回一个不超过指定长度n的流
- skip(n):跳过前面n个元素,和limit互补,实现类似分页功能
使用示例:
1 | java复制代码 // filter示例:过滤出素食的选项 |
2、映射
将每个元素映射处理成一个新的元素,主要实现有:
- map(Function<T,R> f):将函数应用到每个元素上,并将其转换成一个新的元素。
- mapToInt(ToIntFunction f):接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的IntSteam。
- flatMap(Function f):接收一个函数作为参数,将流中的每个值都转换成另外一个流,然后把所有流连接成一个流。
1 | java复制代码 //map示例:Dish对象映射成dishName |
3、查找与匹配
查找或判断数据流中某些元素是否匹配一个给定的属性,常见API如下:
- anyMatch(Predicate p):至少有一个元素匹配给定的谓词
- allMatch(Predicate p):检查是否匹配所有元素
- noneMatch(Predicate p):检查是否没有匹配的元素
- findAny():返回当前流中的任意元素(注意,返回是Optional对象)
- findFirst():返回第一个匹配的元素(和findAny区别是并发流上)
1 | java复制代码 //anyMatch: 是否存在素食 |
4、归约操作
将流中的元素反复结合起来,从而得到一个值,比如最大值、热量总和,这样的操作统称为归约操作。
1 | java复制代码 List<Integer> intList = Arrays.asList(1,3,5,2,4,6); |
5、数值流
这块主要基于数值特点,有两个特殊场景,规避数值类型的装箱问题的基础类型流特化、数值范围两个。
5.1 基础类型流特化
使用reduce对Integer类似对象进行数值计算暗含装拆箱成本,因此StreamAPI提供了IntStream
、DoubleStream
、LongStream
三个基础类型流特化接口来处理,避免了潜在的装箱成本。
1 | java复制代码 // 映射成数值流 |
5.2 数值范围
数值流针对生产指定范围数字的需求,提供了range
和rangeClosed
两个方法,有两个参数,指定范围,后面方法为闭区间。
1 | java复制代码 // 数值范围方法 |
6、构建流
数据元素源时Stream数据处理操作的基石,本小节主要系统介绍除了Collection
外所有可能的流生成方式。
- 由值创建流:利用
Stream.of()
可以直接将值对象封装成Stream - 数组创建:使用
Arrays.stream()
静态方法,将数组直接转换成流 - 文件生成流:主要利用
java.nio.file.Files
工具类来实现,比如lines()
方法 - 由函数生成流:主要时使用
Stream.iterate(final T seed, final UnaryOperator<T> f)
和Stream.generate()
方法来循环调用函数生成无限流。
1 | java复制代码 // 基于值序列创建 |
本文涉及的代码示例地址
本文转载自: 掘金