Try everything using stream api

2019-03-18  本文已影响0人  NazgulSun

最近要学习flink 流处理框架,其中有些概念一上来看还是还是比较confuse。

想起java8 中的stream 编程,他们的设计哲学相似,只不过flink可以处理大规模的数据集。

这篇文章将深入学习,java8 的stream api以及函数式编程。

在网上个人能找到的资料中,下面的git 是写的最好,最深入浅出的。

https://github.com/CarpenterLee/JavaLambdaInternals

对于stream系统的学习,大家可以看上面的git,下面是个人针对上述主题的学习和理解。

1. stream api 的好处

-函数式编程风格,带来的链式的代码,同样的任务,可以用更加简洁的代码来实现。

-我一直认同,编程是关于交流的艺术,简洁意味着交流效率的提升。 函数式风格的代码,其实是更加贴近自然语言的代码

就是一种say what i want to do 的语言, 而不是一种 how i should do 的语言,他告诉计算机要干什么,而不是告诉

计算机每一步具体的细节,这样的哲学就像SQL语言一样。

2. Stream APi 整体的设计思路。

首先,我们得有一个数据源,比如一个 int[]{1,2,3}, 一个collection等。

然后对这个数据源,我们可以定义,我们需要做什么操作。

比较常用的操作就是, filter,map, distinct 等等。

注意,当前的阶段还只是定义操作,不做任何执行。为了方便理解,你可以把数据源理解为数据库,

而定义的操作则是数据库视图view。

最后,stream 定义好View之后,就有一个执行引擎,他负责分析 操作集合,哪些过程是可以在一个for循环一起做的,并叠加结果

而哪些过程是需要依赖前面的结果的。

stream 中有一个 stateful 和stateless 的概念,如果 几个操作可以同时做,那么这几个操作就是无状态的。比如filter,flat等等。

如果一个操作必须要等待前面的操作完成,那么他就是有状态,比如sort排序等。

执行完定义的操作之后,stream 有一个 结果收集器, 可以指定你想要的结果收集方式, 比如 toList, groupby, 或提供reduce函数,这个收集器

实现的非常强大和灵活。

3. 如何实现的?

对于一个 collection.stream().filter().map().sort().collect() java 8是如何实现的呢?

对于每一个操作 比如filter 会抽象成一个stage, stage相连接构成一个链式的流水线。

直白的想法就是流水线的开头,分别调用下一个流stage节点,并检查下一个流水线是否是短路操作(如Collect)

对于java 每个stage 有 begin, end, accept 操作。 begin可以做一些初始化工作,比如sort的begin函数可能初始化一个容器。

而sort 的end 操作可能是进行排序等。

4. 与函数编程的关系

设想让你自己用设计模式实现上述的设计思想,你绕不开的一个问题,就是 filter, map,sort 等方法中,如何能够接收用户提供的函数作为参数,

就像是传入了一个callback一样。

java8 提供了lambda 和Function编程包。 Function编程包基本上可以对现有任何的函数形式进行建模。

比如:有一个参数,一个返回,多个参数多个返回的,都可以抽象成Function对象

而lambda表达式,其实是和函数等价的,只不过lambda更加简洁,javac的类型推到可以正确的把lambda推导成Function类型。

5.性能

stream api 完全是可以用复杂一点的for循环来叠加所有的操作,

根据大神的测试报告,单核情况下,for循环的性能是最好的,但是由于stream 的并发架构,多核情况下,比for循环还要好。

其实,我觉得在大多数的场景下,我们都还不至于计较那些个毫秒的差距。

6. 使用案例

针对collection, map 的所有操作貌似都可以用stream api实现。

try everything using stream in your business

如果不能实现,就去看看stream reduce 的api。

上一篇 下一篇

猜你喜欢

热点阅读