1. Stream 简介
集合
和数组
是经常会用到的数据结构,通常会对它们做增、删、改、查、聚合、统计、过滤等操作。在较早的 Java 版本中对集合和数组的处理并不是很便捷,不过Java 8
添加了一个新的抽象Stream
,可以以一种声明的方式处理数据。Stream
使用一种类似用 SQL
语句从数据库查询数据的直观方式来提供对 Java 集合运算和表达的支持,这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选,排序,聚合等
Stream 的特性如下
:
无存储
Stream不是一种数据结构,只是数据源的一个视图,数据源可以是一个数组,Java容器或 I/O channel 等为函数式编程提供支持
对 Stream 的任何修改都不会修改真实的数据源,比如 Stream 的过滤操作并不会删除过滤掉的元素,而是产生一个不包含被过滤元素的新Stream懒加载思想
Stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行可消费性
Stream只能被最终操作
操作一次,之后就会失效,类似容器的迭代器,想要再次操作必须重新生成。在最终操作之后,再次使用流将抛出异常:java.lang.IllegalStateException: stream has already been operated upon or closed
对于流的处理主要有三种关键性操作:流的创建、中间操作(intermediate operation)以及最终操作(terminal operation)
2. Stream 创建
创建 Stream
流通常有以下几种方法:
-
使用已有集合创建流
在Java 8
中对集合类做了增强,在其中增加了stream
方法,可以将一个集合类转换成流。以下代码通过一个已有的List
调用其stream()
方法创建一个流,这种创建流的方式也是最常用的一种除此以外还有一个
parallelStream()
方法可以为集合创建一个并行流
。parallelStream()
采用多线程来计算,默认的并发线程数要比CPU处理器的数量少1个,因为最优的策略是每个CPU处理器分配一个线程,然而主线程也算一个线程// 1. 集合类转化 Arrays.asList("Nathan", "Hello", "HelloWorld"); Stream<String> stream = strings.stream(); // 2. 数组转化 Stream<String> stream = Arrays.stream(new String[]{"Nathan", "Hello", "HelloWorld"})
-
通过 Stream 创建流
使用Stream
提供的方法可以直接返回一个由指定元素组成的流Stream<String> stream = Stream.of("Nathan", "Hello", "HelloWorld");
3. Stream 常用操作
Stream
的操作主要分为两类:中间操作
和最终操作
。中间操作
得到的结果还是一个Stream
,我们需要借助最终操作
将一个 Stream
转换成想要的类型
3.1 Stream 常用中间操作
操作方法 | 功能 |
---|---|
filter | 将符合指定条件的元素过滤出来 |
map | 以指定的方式将元素映射为另一种类型的数据,其 lambda 表达式必须有返回值 |
flatMap | 与 map 类似,但当其操作的元素是仍然可迭代的数组或集合时,flatMap 会将可迭代数据结构中的元素取出,以指定方式映射后合并为一个流 |
distinct | 对流中的元素去重 |
sorted | 对流进行排序 |
limit | 返回 Stream 的前面 n 个元素 |
skip | 扔掉前 n 个元素 |
3.2 Stream 常用最终操作
操作方法 | 功能 |
---|---|
foreach | 遍历流中的每个元素 |
count | 统计流中的元素个数 |
collect | 归约操作,可将流中的元素组成一个汇总结果,常用参数Collectors.toList() |
max | 统计流中最大对元素,但需要指定元素比较的规则 Comparator |