最近加入了一个有趣的年轻同事,提交了很多代码。打开git记录,结果发现代码是通过使用java8的大量语法特性重新构建的。最常用的是地图、平面地图等。
但是其他朋友不想。虽然有些人觉得代码变得容易理解,但更多的人觉得代码变得晦涩难懂。
感觉就像:脱裤子放屁,重新发明轮子。
我认为这些功能的范围可以根据级别分为三类。几乎无处不在。
不要过分使用我不知道这些函数是什么时候流行起来的,但它们与函数编程密切相关。Scala似乎是从2004年开始的。
没什么神奇的。都是语法糖,用来让你的程序更简洁。如果你愿意,你可以用更多的代码来完成。不要故意用它来炫耀你的技能。事情会变得越来越糟。如果用不好,效果会很负面。比如Java不是函数式编程语言,那么lambda只是一个辅助;而如果用java写Lisp代码,只会不伦不类。
但是语言还是需要整合,因为这是趋势。与其看他们背后的设计,不如让我们从api的语义表示来看他们水平表达了什么。
先来看看共性(注意:逻辑共性并不适合所有场景),然后拿几个典型的实现来看看程序员在这个星球上的表现。
这些抽象的概念这些函数的对象被称为流。具体是什么流程?请原谅我用了一些不专业的词语来解释。
无论是语言层面还是分布式数据结构,其实都是一个简单的数组。有时它确实是一个简单的数组,有时它是一个存在于多台机器中的分布式数组。在下文中,我们将把它统称为数组流。
我们简单地分为两类。
语言层面的:比如Java的Stream分布式层面的:比如Spark的RDD它们都有以下要点。
函数可以用作参数。
c语言当然没问题。函数可以作为指针传入。但不久前,在java中,这不得不绕过弯道来实现(使用java中的Class概念来模拟函数,你会看到很多奇怪的Java类,比如Func1和Func0)。
函数作为参数是使代码简洁的必要条件。我们通常的编程方法大多是按顺序执行一些操作。
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可以在执行后输出结果。这让人没面子。
地图缩小
说到映射和缩减,我们都会想到hadoop。然而,这不仅仅是大数据中的一个概念。
对于他们的概念,我们只在下面两行介绍。
地图
将传入函数依次应用于序列的每个元素,并将结果作为新的数组流返回。
减少
Reduce类似于递归概念。最终会降低到一个值。看这个公式:)
reduce([p1,p2,p3,p4],fn) = reduce([fn(p2,p4),fn(p1,p3)])我们来看看谷歌的经典论文。
《地图缩减:简化数据》
大型集群上的处理”
https://ai.google/research/pubs/pub62
你能来看看吗?:)
地图平面图
这两个函数经常被使用。它们有以下区别:
地图
使用提供的函数对数组流中的每个值执行一次,并进行一一对应。获取具有相同元素数量的数组流。
平面地图
扁平意味着扁平。它使用提供的函数逐个执行数组流中的每个值。获取具有相同元素的数组流。但是,里面的元素也是一个子数组流。在将这些子阵列合并成一个阵列后,大量元素的概率将不同于原始阵列流的概率。
程序员们的表演java8中的八种流
Java8从一个新的抽象开始,叫做Stream: stream。有了lambda语法,代码可以变得特别清新干净(一切都将是Scala)。
一个非常好的向导:
https://stackify.com/streams-guide-java-8/
火花的RDD操作
spark的核心数据模型是RDD,它是一个有向无环图。它表示一个不可变的、可分区的集合,其中元素可以并行计算。
它是分布式的,但是我们可以看下一个单词计数的例子。
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程序是一个执行分布式集合变换(例如,过滤、映射、更新状态、连接、分组、定义窗口、聚合)的例行程序。Flink中的DataStream程序是在数据流上实现的转换。
让我们也来看看它的一段代码。
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已经成为一个分布式流计算平台。他抽象出了一个KStream和KTable,它们类似于Spark的RDD,有着相似的操作。
KStream可以看作是KTable的更新日志,数据流中的每一条记录都对应着数据库中的每一次更新。
让我们看看它的一段代码。
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开发中经常用到(使用的服务器越来越多)。
RX语言层面有所创新,也有一些忠实的信徒。
语言层面的λ
当然,Haskell这种自然的函数式编程语言也有自己的光环。但是其他语言,包括脚本语言和编译语言,也吸收了这些经验。
它们统称为λ。
计算机编程语言
作为最流行的脚本语言,python也有它的lambda语法。最基本的功能,如地图,减少和过滤也存在。
Java Script语言
Js也拉不下来,比如Array.prototype.*()等等。它拥有它应得的一切。
End还有很多,我就不一一列举了。换句话说,这些功能可以申请专利吗?我非常喜欢它,尽管我很少使用它。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 ZLME@xxxxxxxx@hotmail.com 举报,一经查实,立刻删除。