map是什么意思(到处是map、flatMap,啥意思?)

map是什么意思(到处是map、flatMap,啥意思?)

最近加入了一个有趣的年轻同事,提交了很多代码。查看git记录,结果发现java8的很多语法特性都被用来重构代码。最常用的有map,flatMap之类的。

但是其他朋友不愿意。虽然有人觉得代码变得通俗易懂,但更多人觉得代码变得晦涩难懂。

感觉就像:脱裤子放屁,多此一举。

这些职能的范围,按照级别,我认为可以分为三类。几乎无处不在。

不要过度。

我不知道这些函数是从什么时候开始流行的,但是它们和函数编程的关系肯定是非常密切的。好像Scala是从2004年开始的。

这没什么神奇的。都是语法糖,作用是让你的程序更简洁。如果你愿意,你可以用更多的代码来实现它。不要故意用它来炫耀自己的技能。事情会变得相反。如果用不好,效果会很负面。比如java不是函数式编程语言,所以lambda只是辅助;而如果用java写Lisp代码,那就不伦不类了。

但是语言还是要融合,因为这是趋势。不看它们背后的设计,只从api的语义表示上看它们横向表达了什么。

我们先来看共性(注:逻辑共性并不适用于所有场景),然后取几个典型的实现,看看这个星球上程序员的表现。

这些抽象的概念

这些函数的对象被称为流。溪流是一种什么东西?请原谅我用一些不专业的话来解释。

它实际上是一个简单的数组,无论是语言层面还是分布式数据结构。有时它真的是一个简单的数组,有时它是存在于多台机器中的分布式数组。以下,我们统称为数组流。

我们简单分为两类。

语言层面的:比如Java的Stream分布式层面的:比如Spark的RDD

都有以下几个重点。

函数可以用作参数。

c语言当然可以,可以传入函数作为指针。但不久前,在java中,这是要绕弯的(用java concept中的类来模拟函数,会看到很多Func1、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)...

编程模式完全变了,函数有了语义。

顺序和并行

如果我们的数组流太大,对于单机来说,有两种方式:顺序处理和并行处理。

一般可以通过并行功能进入并行处理模式。对于大多数本地操作,并行不一定很快。

用java里的ForkJoin,线程的速度,你懂的…

但是对于分布式数据流来说,是并行的,所以这个参数意义不大。

功能类别

通常,作用于数据流的函数可以分为两类。

转换。Transformation动作。Action

转换的典型特征就是懒。

只有执行了动作,才会真正参与到操作中。因此,您可以将这些转换操作视为一组缓冲操作。典型功能如:地图、平面地图等。它们像串肉扦一样串在一起,等着被卷起来。

行动。真正触发代码的操作,上面的一系列转换,也会像打开闸门的洪水。典型的如reduce函数,就是这个。

上面的描述也不尽然,比如python的map,可以输出执行后的结果。很尴尬。

映射和缩小

说到map和reduce,大家想到的都是hadoop。然而,它不仅仅是大数据中的一个概念。

对于他们的概念,我们只介绍以下两行。

地图

将传入的函数依次应用于序列的每个元素,并将结果作为新的数组流返回。

减少

Reduce类似于一个递归概念。最终会缩减为一个值。看这个公式:)

reduce([p1,p2,p3,p4],fn) = reduce([fn(p2,p4),fn(p1,p3)])

具体看一下Google的经典论文。

《MapReduce:简化数据》

大型集群上的处理》

https://ai.google/research/pubs/pub62

你能参观吗?:)

地图和平面图

这两个函数经常用到。它们有以下不同之处:

地图

使用提供的函数执行数组流中的每个值,并一一对应。获取具有相同元素数量的数组流。

平面地图

平就是平的意思。它使用提供的函数来执行数组流中的每一个值,并且一一对应。获取具有相同元素的数组流。但是,里面的元素也是一个子数组流。这些子数组合并成一个数组后,元素的数量将与原始数组流的数量不同。

程序员的表现

八种java8流

Java8开始于添加一个新的抽象,叫做Stream: stream。有了lambda语法,代码可以变得特别清爽干净(如果你发现什么的话,一定是Scala)。

一个非常好的指南:

https://stackify.com/streams-guide-java-8/

火花的RDD操作

spark的核心数据模型是RDD,这是一个有向无环图。它表示一个不可变的、可划分的集合,其中的元素可以并行计算。

它是分布式的,但是我们可以看看WordCount的下一个例子。

JavaRDD textFile = sc.te嘉文社百科xtFile(\"hdfs://...\");JavaPairRDD counts = textFile .flatMap(s -> Arrays.asList(s.split(\" \")).iterator()) .mapToPair(word -> new Tuple2(word, 1)) .reduceByKey((a, b) -> a + b);counts.saveAsTextFile(\"hdfs://...&q嘉文社百科uot;);

好熟悉的Api。你一定在Hadoop里见过。

弗林克数据流

Flink程序是执行分布式集合转换(例如,过滤、映射、更新状态、联接、分组、定义窗口、聚合)的例行程序。Flink中的数据流程序是在数据流上实现的转换。

让我们也来看看它的一段代码。

DataStream 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&嘉文社百科nbsp;\"1\".keyBy(0).sum(1);

卡夫卡流的运作

Kafka已经成为一个分布式流计算平台。他抽象出了一个KStream和KTable,类似于Spark的RDD,有着相似的操作。

KStream可以看作是KTable的更新日志,数据流中的每一条记录都对应着数据库中的每一次更新。

让我们来看看它的一段代码。

KTable 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

Rx是一个基于观察者模式的异步任务框架,在Android开发中经常使用(越来越多的被服务器使用)。

Rx在语言层面做了一些创新,也有一些忠实的信徒。

语言层面的Lambda

当然,Haskell这种自然的函数式编程语言自有它的光环。但是其他语言,包括脚本语言和编译语言,也吸收了这些经验。

它们统称为λ。

计算机编程语言

作为最流行的脚本语言,python也有它的lambda语法。最基本的贴图、还原、过滤等功能也是有的。

Java Script语言

Js也拉不下来,比如Array.prototype.*()等。该有的都有了。

目标

还有很多,就不一一列举了。对了,这些功能可以申请专利吗?很喜欢,虽然很少用。

以上就是由优质生活领域创作者 嘉文社百科网小编 整理编辑的,如果觉得有帮助欢迎收藏转发~