Java 8 中的 Streams API

Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation) 同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。

Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性,是一个函数式语言+多核时代综合影响的产物。

什么是聚合操作

在传统的 J2EE 应用中,Java 代码经常不得不依赖于关系型数据库的聚合操作来完成诸如:

  • 客户每月平均消费金额
  • 最昂贵的在售商品
  • 本周完成的有效订单(排除了无效的)
  • 取十个数据样本作为首页推荐

但如果脱离DBMS,在底层数据上进行数据统计,java可借用的工具太少,在stream之前通常用 Iterator 来遍历集合

什么是stream

Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级Iterator。

原始Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作,

高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 过滤掉长度大于 10 的字符串,Stream 会隐式地在内部进行遍历,做出相应的数据转换。

Stream 就如同一个迭代器,单向,不可往复,数据只能遍历一次。

和迭代器的不同

Stream 可以并行化操作,迭代器只能命令式地、串行化操作。顾名思义,当使用串行方式去遍历时,每个 item 读完后再读下一个 item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。Stream 的并行操作依赖于 Java7 中引入的 Fork/Join 框架(JSR166y)来拆分任务和加速处理过程。Java 的并行 API 演变历程基本如下:

  1. 1.0-1.4 中的 java.lang.Thread
  2. 5.0 中的 java.util.concurrent
  3. 6.0 中的 Phasers 等
  4. 7.0 中的 Fork/Join 框架
  5. 8.0 中的 Lambda

Stream 的另一特点是,数据源本身可以是无限的。

stream的构成

stream的操作类型分为两种:

  • Intermediate:一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。
  • Terminal:一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。

在对于一个 Stream 进行多次转换操作 (Intermediate 操作),每次都对 Stream 的每个元素进行转换,而且是执行多次,这样时间复杂度就是 N(转换次数)个 for 循环里把所有操作都做掉的总和吗?其实不是这样的,转换操作都是 lazy 的,多个转换操作只会在 Terminal 操作的时候融合起来,一次循环完成。我们可以这样简单的理解,Stream 里有个操作函数的集合,每次转换操作就是把转换函数放入这个集合中,在 Terminal 操作的时候循环 Stream 对应的集合,然后对每个元素执行所有的函数。

还有一种操作被称为 short-circuiting。用以指:

  • 对于一个 intermediate 操作,如果它接受的是一个无限大(infinite/unbounded)的 Stream,但返回一个有限的新 Stream。
  • 对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。

当操作一个无限大的 Stream,而又希望在有限时间内完成操作,则在管道内拥有一个 short-circuiting 操作是必要非充分条件。

操作类型

  • Intermediate:

map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

  • Terminal:

forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

  • Short-circuiting:

anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

原文地址:https://www.cnblogs.com/Ryez/p/11263481.html

时间: 2024-08-12 20:35:41

Java 8 中的 Streams API的相关文章

Java 8 中的 Streams API 详解

为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream.Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggregate operation),或者大批量数据操作 (

Java进阶教程:Streams API

Java进阶教程:Streams API Stream是啥 首先明确一点,Stream流和IO包里的InputStream.OutputStream是完全不同的概念!它是Java 8 中引入的新特性,Stream可以对集合元素进行各种高效.便利的聚合操作! 聚合是个什么东东呢? 聚合在信息科学中是指对有关的数据进行内容挑选.分析.归类,最后分析得到人们想要的结果,主要是指任何能够从数组产生标量值的数据转换过程 [1]  .近年来随着大数据的发展,聚合技术已经广泛地应用于文本分析,信息安全,网络传

Java 8 Streams API 详解

流式编程作为Java 8的亮点之一,是继Java 5之后对集合的再一次升级,可以说Java 8几大特性中,Streams API 是作为Java 函数式的主角来设计的,夸张的说,有了Streams API之后,万物皆可一行代码. 什么是Stream Stream被翻译为流,它的工作过程像将一瓶水导入有很多过滤阀的管道一样,水每经过一个过滤阀,便被操作一次,比如过滤,转换等,最后管道的另外一头有一个容器负责接收剩下的水. 示意图如下: 首先通过source产生流,然后依次通过一些中间操作,比如过滤

java 8 中的stream

Java 8 中的 Streams 详解 Java 8 是迄今为止在语义上改动上最大的一个平台.除了最显著的 Lambda 表达式之外,还有很多初次见面的特性,例如本文主题的 Streams API.这里介绍了它出现的背景和具体用法. 为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesi

深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)

转:http://zh.lucida.me/blog/java-8-lambdas-inside-out-library-features/ 关于 深入理解 Java 8 Lambda(语言篇--lambda,方法引用,目标类型和默认方法) 深入理解 Java 8 Lambda(类库篇--Streams API,Collector 和并行) 深入理解 Java 8 Lambda(原理篇--Java 编译器如何处理 lambda) 本文是深入理解 Java 8 Lambda 系列的第二篇,主要介绍

[转]深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)

以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-library-features 本文谢绝转载,如需转载需征得作者本人同意,谢谢. -------------------------------------内容分割线--------------------------------------------------------- 深入理解Java

【Socket编程】Java中网络相关API的应用

Java中网络相关API的应用 一.InetAddress类 InetAddress类用于标识网络上的硬件资源,表示互联网协议(IP)地址. InetAddress类没有构造方法,所以不能直接new出一个对象: InetAddress类可以通过InetAddress类的静态方法获得InetAddress的对象: 1 InetAddress.getLocalHost();//获取本地对象 2 InetAddress.getByName("");//获取指定名称对象 主要方法使用: 1 /

Salesforce中通过SOAP API和Metadata API开发java的web server服务

1.下载Salesforce平台中WSDL文件 在Salesforce中创建了自己需要用到的对象后,我们想要在别的应用中读写纪录到对象中,首先需要的是自己Salesforce平台的权限通过.登陆自己的Salesforce,下载WSDL文件. 依次点击右上角你的名字中设置-->应用程序设置-->发展-->API. 如果你的是英文,那么依次点击Your Name --> Setup --> App Setup --> Develop --> API. 到了如下页面后,

java 8中新的日期和时间API

java 8中新的日期和时间API 使用LocalDate和LocalTime LocalDate的实例是一个不可变对象,它只提供了简单的日期,并不含当天的时间信息.另外,它也不附带任何与时区相关的信息 LocalDate实例提供了多种方法来读取常用的值,比如年份,月份,星期几等 LocalDate date = LocalDate.of(2014,3,18); int year = date.getYear(); Month month = date.getMonth(); int day =