Java Stream 整理
流的结构
所有流计算都有一种共同的结构:
- 一个
流来源
(Collection::stream, Arrays::stream, Stream::generate)- 流的来源大部分是
集合
,也可以从数组
、生成器工厂
等来源。
- 流的来源大部分是
- 零或多个
中间操作
- 将一个流转换成另一个流。
惰性
:调用中间操作只会设置流管道的下一个阶段,不会启动任何操作。状态性
- 有状态:合并以前看到的影响其他元素处理的元素状态。(sorted, distinct)
- 无状态:独立处理每个元素。(filter, map)
- 一个
终止操作
(toArray, reduce, collect)- 生成一个结果或副作用。
- 终止后如果要再次遍历同一个数据集,需要设置一个新的流管道。
流的注重点:计算
源 | 计算 | 计算 | … | 计算 | 终止 |
—————————————> 一轮 -> 下一个元素
—————————————> 又一轮 -> 下一个元素
—————————————> 再一轮 -> 下一个元素
…
惰性
对于流,只有 终止 操作是 急切 的;其他操作 都是 惰性 的。流操作表示其输入(也是流)上的功能转换,而不是数据集上的突变性操作(过滤一个流会 生成一个新流,新流的元素 是输入流的子集,但没有从来源删除任何元素)。
短路
短路类似于 C++
/Java
中的 if
中带有 &&
的判断。
操作融合
在数据上的一轮中执行多个操作。“深度优先”,提高数据在缓存中的利用率(数据更“热”),提升性能。
并行性
并行性并不是高性能的原因。并行执行可能比顺序执行更快、一样快或更慢。 最好先从顺序流开始。
lambda的限制
互不干扰
它们不会修改流来源。
无状态
它们不会访问(读或写)任何可能在流操作寿命内改变的状态。
关于副作用
最好是无副作用:它们不会突变任何基于堆的状态或在执行过程中执行任何 I/O。
否则,会进行协调,以确保这些副作用是线程安全的。同时,副作用可能被优化掉不执行。