什么是 Stream
Stream(流)是一个来自数据源的元素队列并支持聚合操作。
在 Java 中,集合和数组是我们经常会用到的数据结构,但是在 Java 8 之前,集合和数组的处理并不是很便捷,
这一问题在 Java 8 中得到了改善,Java 8 API 添加了一个新的抽象称为流 Stream。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API 可以极大提高 Java 程序员的生产力,让程序员写出高效率、干净、简洁的代码。
流的处理,主要有三种关键性操作:分别是流的创建、中间操作(intermediate operation)以及最终操作(terminal operation)
Stream 的创建
通过已有的数组来创建流
1 | String[] arr = new String[] {"ab", "cd", "ef"}; |
通过已有的集合来创建流
1 | List<String> strings = Arrays.asList("Hello", "World", "Hello World", "Hello Stream"); |
通过 Stream 创建流
1 | Stream<String> stream = Stream.of("Hello", "World", "Hello World", "Hello Stream"); |
Stream 中间操作
中间操作总是会惰式执行,调用中间操作只会生成一个标记了该操作的新 stream。
filter
filter 用于通过设置的条件过滤出元素,以下代码使用 filter 方法过滤掉空字符串:
1 | List<String> strings = Arrays.asList("Hello", "", "World", "Hello World", "Hello Stream"); |
map
map 用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:
1 | List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); |
limit/skip
limit/skip limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素。以下代码片段使用 limit 方法保留4个元素:
1 | List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); |
sorted
sorted 用于对流进行排序
1 | List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); |
distinct
distinct 主要用来去重
1 | List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); |
Stream 最终操作
最终操作会触发实际计算,计算发生时会把所有中间操作积攒的操作以 pipeline 的方式执行,这样可以减少迭代次数。计算完成之后 stream 就会失效。
最终操作会消耗流,产生一个最终结果。也就是说,在最终操作之后,不能再次使用流,也不能在使用任何中间操作,否则将抛出异常。
常用的最终操作如下:
forEach
forEach 迭代流中的每个数据
1 | Random random = new Random(); |
count
count 用来统计流中的元素个数
1 | List<String> strings = Arrays.asList("Hello", "Stream"); |
collect
collect 一个归约操作,可以接受各种做法作为参数,将流中的元素累积成一个汇总结果
1 | List<String> strings = Arrays.asList("Hello", "World", "Hello Stream"); |
并行(parallel)程序
parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量:
1 | List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); |
Collectors
Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
1 | List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl"); |
统计
一些产生统计结果的收集器也非常有用。它们主要用于 int、double、long 等基本类型上,它们可以用来产生类似如下的统计结果。
1 | List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); |