持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
1. Stream 介绍
1.1 什么是 Stream
Stream 将要处理的元素集合看作一种流,在流的过程中,借助 Stream 类提供的 API 方法可以对流中的元素进行操作,如筛选、排序、聚合等。
Stream 操作拥有以下特性:
-
Stream 不存储数据,而只是按照特定的规则对数据进行计算,并最终输出结果
-
Stream 不会改变源数据内容,操作之后的流会生成一个新的集合或值
-
Stream 具有延迟执行的特性,只有当调用终端操作时,中间操作才会执行
1.2 如何创建 Stream
Stream 的创建不止一种方式,可以根据数据的格式选择合适的创建方式
-
集合创建,Collection 的 stream() 方法,
IntStream stream = list/set.stream(); -
数组创建,Arrays 的 stream() 方法,
IntStream stream = Arrays.stream(array); -
Stream 的静态方法,如 of、iterate、generate 等,可以传入数据源并返回 Stream 结果
// 参数可以传入多个参数,生成 Stream 流对象
Stream.of(1,2,3,4,5);
// 传入初始元素和步幅,根据规则产生有序的队列
Stream.iterate(0, (x) -> x+3).limit(4);
// 根据参数指定的方法产生无序的序列
Stream.gengrate(Math::random).limit(4);
- 文件流,Files 的 lines() 方法,文件生成的每个流是文件中的一行数据
Stream<String> lines = Files.lines(Paths.get("test.txt"), Charset.defaultCharset())
1.3 Stream 流的种类
Stream 根据流的种类和内容机制可以分为顺序流和并行流
-
顺序流,即 Stream,上述方法生成的皆是顺序流
-
并行流,即 ParallelStream,可以通过
list.parallelStream()方式创建并行流 -
顺序流可以通过方法转换成为并行流,
list.stream().parallel();
1.4 Stream 调试
在程序中,如果使用了 Stream 流式表达式,则在调试流程中默认是无法进入流过程中,可以在 IDEA 中设置开启。
- IDEA 控制台按钮最右侧:Trace Current Stream Chain
2. Stream 使用(过程操作)
在 Stream 流中,元素是以 Optional 类型存在的,Optional 也是 Java8 新增加的类型,它通过对对象的封装来减少判断对象为 null 的情况,使用时可以更加关注程序本身。
2.1 filter 筛选
通过使用 filter 方法进行条件筛选,filter 的方法参数为一个条件,使用时对流通过指定条件进行过滤,最终返回满足条件的流。
list.stream().filter(o -> o.getId() == userId);
2.2 distinct 去重复
distinct 方法可以对集合中的元素进行去重处理,主要针对集合中元素为基本类型或字符串时使用。
list.stream().distinct();
2.3 sort 排序
sort 方法可以对流中的元素按照自然顺序或自定义顺序排序,也可以对排序序列反转。
list.stream().sorted();
2.4 map 映射
map 方法可以接收一个 Function 函数,该函数会应用到流中的每个元素,并最终得到映射的元素结果。
// 流中元素转小写
Arrays.stream(array).map(String::toUpperCase);
2.5 foreach 遍历
foreach 方法类似 Java 中的 for 循环,可以将 Stream 流中的元素进行循环遍历,并进行相关的处理。
// 生成流并遍历打印流中的元素
Stream.of(1, 2, 3, 4, 5, 6).forEach(System.out::println);
3. Stream 使用(结果操作)
使用中间操作处理 Stream 流得到的结果仍然是流,要想得到 Java 中对应的数据类型,还需要使用 Stream 的结果操作,并指定流转成的对象类型。
3.1 collect() 收集
collect() 收集方法可以将流中的元素按照指定方式收集起来,并转成指定类型数据。
最常见的即将处理后的 List 流转成 List 结构
List list = list.stream().filter(o -> o.getId() == userId).collect(Collectors.toList());
除了 Collectors.toList() 方法,Collectors 中还提供了 .toSet() 和 .toMap() 等类型的转换方法。
3.2 count 统计
除了直接转成集合类型,还可以使用统计的方式来对流进行结果操作,如对流中的元素计算数量、累加值、平均值等操作。
// 计算数量
Long count = personList.stream().collect(Collectors.counting());
Collectors 中还有其他如 averagingInt() 和 maxBy() 等方法。
3.3 groupingBy 分组
根据流中的对象中指定属性,实现对流中对象分组后执行结果操作,返回分组类型 Map<Type,Object>
Map<Type,User> map = list.stream().collect(groupingBy(User::getName));
4 总结
本篇文章先对 Stream 的整体有个初步认识,具体的方法使用接下来继续输出!