Java 8 开始新增的 Stream(流)是一个来自数据源的元素队列并支持聚合操作。
-
元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
-
数据源:流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
-
聚合操作:类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
-
Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
-
内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
Java 8 新增了 Stream、IntStream、LongStream、DoubleStream 等流式 API,这些 API 代表多个支持串行和并行聚集操作的元素。Stream 是一个通用的流接口,而 IntStream、LongStream、 DoubleStream 则代表元素类型为 int、long、double 的流。
Java 8 还为上面每个流式 API 提供了对应的 Builder,例如 Stream.Builder、IntStream.Builder、LongStream.Builder、DoubleStream.Builder,开发者可以通过这些 Builder 来创建对应的流。
独立使用 Stream 的步骤如下:
-
使用 Stream 或 XxxStream 的 builder() 类方法创建该 Stream 对应的 Builder。
-
重复调用 Builder 的 add() 方法向该流中添加多个元素。
-
调用 Builder 的 build() 方法获取对应的 Stream。
-
调用 Stream 的聚集方法。
Stream 提供了大量的方法进行聚集操作,这些方法既可以是“中间的”(intermediate),也可以是 "末端的"(terminal)。
-
中间方法:中间操作允许流保持打开状态,并允许直接调用后续方法。中间方法的返回值是另外一个流。
-
末端方法:末端方法是对流的最终操作。当对某个 Stream 执行末端方法后,该流将会被“消耗”且不再可用。sum()、count()、average() 等方法都是末端方法。
除此之外,关于流的方法还有如下两个特征。
-
有状态的方法:这种方法会给流增加一些新的属性,比如元素的唯一性、元素的最大数量、保证元素以排序的方式被处理等。有状态的方法往往需要更大的性能开销。
-
短路方法:短路方法可以尽早结束对流的操作,不必检查所有的元素。
除此之外,Java 8 允许使用流式 API 来操作集合,Collection 接口提供了一个 stream() 默认方法,该方法可返回该集合对应的流,接下来即可通过流式 API 来操作集合元素。由于 Stream 可以对集合元素进行整体的聚集操作,因此 Stream 极大地丰富了集合的功能。