Stream

为什么需要 Stream

Java8中的stream与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念,也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream,它是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。

Stream的特性

在集合和其他数据集上运行函数式查询。Stream可以认为是一个高级版本的Iterator,它代表着数据流,流中的数据元素的数量可以是有限的,也可以是无限的。其差别在于:
  无存储:Stream是基于数据源的对象,它本身不存储数据元素,而是通过管道将数据源的元素传递给操作。
  函数式编程:对Stream的任何修改都不会修改背后的数据源,比如对Sream的filter操作并不会删除被过滤掉的元素,而是生成一个不含被过滤元素的新的Stream。
  延迟执行:Stream由一个或多个中间操作(intermediate operation)和一个结束操作(terminal operation)两部分组成。只有执行了结束操作,Stream定义的中间操作才会依次执行,这就是Stream的延迟特性。
  可消费性:Stream只能被“消费”一次,一旦遍历过就会失效。就像容器的迭代器那样,想要再次遍历必须重新生成一个新的Stream。

流管道剖析

JDK 中的流来源


方法 描述
Collection.stream() 使用一个集合的元素创建一个流
Stream.of(T…) 使用传递给工厂方法的参数创建一个流
Stream.of(T[]) 使用一个数组的元素创建一个流

中间流操作

操作 描述
filter(Predicate) 与预期匹配的流的元素
map(Function<T, U>) 将提供的函数应用于流的元素的结果
flatMap(Function<T, Stream> 将提供的流处理函数应用于流元素后获得的流元素
distinct() 已删除了重复的流元素
sorted() 按自然顺序排序的流元素
Sorted(Comparator) 按提供的比较符排序的流元素
limit(long) 截断至所提供长度的流元素
skip(long) 丢弃了前 N 个元素的流元素
takeWhile(Predicate) (仅限 Java 9)在第一个提供的预期不是 true 的元素处阶段的流元素
dropWhile(Predicate) (仅限 Java 9)丢弃了所提供的预期为 true 的初始元素分段的流元素

中间操作始终是惰性的调用中间操作只会设置流管道的下一个阶段,不会启动任何操作。重建操作可进一步划分为无状态有状态 操作。无状态操作(比如 filter() 或 map())可独立处理每个元素,而有状态操作(比如 sorted() 或 distinct())可合并以前看到的影响其他元素处理的元素状态。

终止流操作

操作 描述
forEach(Consumer action) 将提供的操作应用于流的每个元素。
toArray() 使用流的元素创建一个数组。
reduce(…) 将流的元素聚合为一个汇总值。
collect(…) 将流的元素聚合到一个汇总结果容器中。
min(Comparator) 通过比较符返回流的最小元素。
max(Comparator) 通过比较符返回流的最大元素。
count() 返回流的大小。
{any,all,none}Match(Predicate) 返回流的任何/所有元素是否与提供的预期相匹配。
findFirst() 返回流的第一个元素(如果有)。
findAny() 返回流的任何元素(如果有)。

附加信息

大多数流操作都要求传递给它们的拉姆达表达是互不干扰无状态的。互不干扰意味着它们不会修改流来源无状态意味着它们不会访问(读或写)任何可能在流操作寿命内改变的状态。对于缩减操作(例如计算 sum、min 或 max 等汇总数据),传递给这些操作的拉姆达表达式必须是结合性 的(或遵守类似的要求)。

如下使用有状态拉姆达表达式的流管道(不要这么做!)

HashSet<Integer> twiceSeen = new HashSet<>();
int[] result
    = elements.stream()
              .filter(e -> {
   
                  twiceSeen.add(e * 2);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值