處處是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

另外還有不少不少,就不一一羅列了。話說,這些函數能夠申請專利麼?我很喜歡,雖然我不多用。

相關文章
相關標籤/搜索