处处是map、flatMap,啥意思?

更多精彩文章。java

《微服务不是所有,只是特定领域的子集》python

《“分库分表" ?选型和流程要慎重,不然会失控》git

这么多监控组件,总有一款适合你程序员

《使用Netty,咱们到底在开发些什么?》数据库

《这多是最中肯的Redis规范了》编程

《程序员画像,十年沉浮》vim

最有用系列:windows

《Linux生产环境上,最经常使用的一套“vim“技巧》api

《Linux生产环境上,最经常使用的一套“Sed“技巧》数组

《Linux生产环境上,最经常使用的一套“AWK“技巧》


最近入职一个有趣的年轻同事,提交了大量大量的代码。翻开git记录一看,原来是用了很是多的java8的语法特性,重构了代码。用的最多的,就是mapflatMap之类的。 可是其余小伙伴不肯意了,虽然有的人感受代码变的容易懂了,但有更多的人感受代码变的很晦涩。 那感受就像是:脱了裤子放屁,画蛇添足。

这些函数的做用域,根据级别,我以为能够分为三类。简直是无所不在。

不要过度使用

我也不知道这些函数是从何时流行起来的,但它们与函数编程的关系确定是很是密切的。好像是2004年的Scala开始的。

没什么神奇的,它们所有是语法糖,做用是让你的程序更简洁。你要是想,彻底能够用多一点的代码去实现。不要为了炫技刻意去使用,物极必反,用很差的话,产生的效果会是很是负面的。好比java,它并非一门函数编程语言,那么lambda就只是一种辅助;而你用java那一套去写Lisp代码的话,也只会不三不四。

但语言仍是要融合的,由于潮流就是这样。不去看他们背后的设计,咱们仅从api的语义表象,横向看一下它们所表达的东西。

咱们首先看一下其中的共性(注意:逻辑共性,并不适合全部场景),而后拿几个典型的实现,看一下在这个星球上,程序员们的表演。

这些抽象的概念

这些函数的做用对象,听说是一种称之为流的东西。那究竟是一种什么东西呢?请原谅我用一些不专业的话去解释。

不管是在语言层面仍是分布式数据结构上,它实际上是一个简单的数组。它有时候真的是一个简单的数组,有时候是存在于多台机器的分布式数组。在下文中,咱们统称为数组流

咱们简单分为两类。

语言层面的:好比Java的Stream
分布式层面的:好比Spark的RDD
复制代码

它们都有如下几个比较重要的点。

函数能够做为参数

C语言固然是没问题的,能够把函数做为指针传入。但在不久以前,在Java中,这还得绕着弯子去实现(使用java概念中的Class去模拟函数,你会见到不少Func一、Func0这样奇怪的java类)。

函数做参数,是使得代码变得简洁的一个必要条件。咱们一般的编程方法,大可能是顺序执行一些操做。

array = new Array()
array = func1(array)
if(func2(array)){
    array = func3(array)
}
array = func4(array)
复制代码

而若是函数可以当参数,我就可以尽可能的将操做平铺。最终,仍是要翻译成上面的语句进行执行的。

array = new Array()
array.stream()
.map(func1)
.filter(func2)
.flatMap(func3)
.sorted(func4)
...
复制代码

编程模式彻底变了,函数也有了语义。

sequential & parallel

若是咱们的数组流太大,对于单机来讲,就有顺序处理和并行处理两种方式。

一般,能够经过parallel函数进入并行处理模式。对于大多数本地操做,开了并行不见得必定会快。 java中使用ForkJoin那一套,线程的速度,你知道的...

而对于分布式数据流来讲,原本就是并行的,这种参数意义就不大了。

函数种类

通常做用在数据流上的函数,会分为两类。

转换。Transformation
动做。Action
复制代码

转换,典型的特色就是lazy。 只有action执行的时候,才会真正参与运算。因此,你能够认为这些转换动做是一套被缓冲的操做。典型的函数如:map、flatMap等。它们就像烤串同样被串在一块儿,等着被撸。

动做。真正触发代码的运行,上面的一系列转换,也会像开了闸的洪水同样,一泻而下。典型的如reduce函数,就是这种。

以上的描述也不尽然,好比python的map,执行后就能够输出结果。这让人很没面子啊。

map & reduce

谈到map和reduce,你们就不约而同的想到了hadoop。然而,它不只仅是大数据中的概念。

对于它俩的概念,咱们仅作下面两行介绍。

map

将传入的函数依次做用到序列的每一个元素,并把结果做为新的数组流返回。

reduce

reduce相似于一个递归的概念。最终会归约成一个值。看看这个公式:)

reduce([p1,p2,p3,p4],fn) = reduce([fn(p2,p4),fn(p1,p3)])
复制代码

具体仍是看谷歌的经典论文吧。

《MapReduce: Simplified Data Processing on Large Clusters》 ai.google/research/pu…

你能访问么?:)

map & flatMap

这两个函数常常被使用。它们有以下区别:

map

数组流中的每个值,使用所提供的函数执行一遍,一一对应。获得元素个数相同的数组流

flatMap

flat是扁平的意思。它把数组流中的每个值,使用所提供的函数执行一遍,一一对应。获得元素相同的数组流。只不过,里面的元素也是一个子数组流。把这些子数组合并成一个数组之后,元素个数大几率会和原数组流的个数不一样。

程序员们的表演

java8种的Stream

java8开始,加入了一个新的抽象,一个称之为流的东西:Stream。配合lambda语法,可使代码变的特别的清爽、干净(有木有发现都快成了Scala了)。

一个很是好的向导: stackify.com/streams-gui…

Spark的RDD操做

spark的核心数据模型就是RDD,是一个有向无环图。它表明一个不可变、可分区、其内元素可并行计算的集合。 它是分布式的,但咱们能够看下一个WordCount的例子。

JavaRDD<String> textFile = sc.textFile("hdfs://...");
JavaPairRDD<String, Integer> counts = textFile
    .flatMap(s -> Arrays.asList(s.split(" ")).iterator())
    .mapToPair(word -> new Tuple2<>(word, 1))
    .reduceByKey((a, b) -> a + b);
counts.saveAsTextFile("hdfs://...");
复制代码

多么熟悉的Api啊,你必定在Hadoop里见过。

Flink 的 DataStream

Flink程序是执行分布式集合转换(例如,filtering, mapping, updating state, joining, grouping, defining windows, aggregating)的常规程序。Flink中的DataStream程序是实如今数据流上的transformation。

咱们一样看一下它的一段代码。

DataStream<Tuple2<String, Integer>> counts =
// split up the lines in pairs (2-tuples) containing: (word,1)
text.flatMap(new Tokenizer())
// group by the tuple field "0" and sum up tuple field "1"
.keyBy(0).sum(1);
复制代码

kafka stream的操做

kafka已经变成了一个分布式的流式计算平台。他抽象出一个KStreamKTable,与Spark的RDD相似,也有相似的操做。

KStream能够看做是KTable的更新日志(changlog),数据流中的每个记录对应数据库中的每一次更新。

咱们来看下它的一段代码。

KTable<String, Long> wordCounts = textLines
.flatMapValues(value -> Arrays.asList(value.toLowerCase().split("\\W+")))
.groupBy((key, value) -> value)
.count();
wordCounts.toStream().to("streams-wordcount-output", Produced.with(stringSerde, longSerde));
复制代码

RxJava

RxJava是一个基于观察者模式的异步任务框架,常常看到会被用到Android开发中(服务端采用的也愈来愈多)。

RxJava再语言层面进行了一些创新,有一部分忠实的信徒。

语言层面的lambda

固然,对Haskell这种天生的函数编程语言来讲,是自带光环的。但其余的一些语言,包括脚本语言,编译性语言,也吸取了这些经验。

它们统称为lambda。

Python

做为最流行的脚本语言,python一样也有它的lambda语法。最基本的map、reduce、filter等函数一样是存在的。

JavaScript

js也不能拉下,好比Array.prototype.*()等。它该有的,也都有了。

End

另外还有不少不少,就不一一罗列了。话说,这些函数能够申请专利么?我很喜欢,虽然我不多用。

相关文章
相关标签/搜索