最近加入了一个有趣的年轻同事,提交了很多代码。查看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.*()等。该有的都有了。
目标
还有很多,就不一一列举了。对了,这些功能可以申请专利吗?很喜欢,虽然很少用。
以上就是由优质生活领域创作者 嘉文社百科网小编 整理编辑的,如果觉得有帮助欢迎收藏转发~
本文地址:https://www.jwshe.com/642099.html,转载请说明来源于:嘉文社百科网
声明:本站部分文章来自网络,如无特殊说明或标注,均为本站原创发布。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。分享目的仅供大家学习与参考,不代表本站立场。