函數(shù)式編程
定義
函數(shù)式編程(funcational programming)屬于結(jié)構(gòu)化編程的一種赁还。主要思想是把運算過程盡量寫成一系列嵌套的函數(shù)調(diào)用窗声。
結(jié)構(gòu)化編程
一種編程范型响谓,采用子程序撞蚕、代碼區(qū)塊笛钝、for循環(huán)以及while循環(huán) 等結(jié)構(gòu)來取代傳統(tǒng)的goto
艰猬。
函數(shù)式編程關(guān)心數(shù)據(jù)的映射,命令式編程關(guān)心解決問題的步驟斧账。
特點
函數(shù)是“第一等公民”
函數(shù)和其他數(shù)據(jù)類型一樣谴返,可以賦值給其他變量,作為其他函數(shù)的傳入?yún)?shù)或返回值其骄。只用“表達式”亏镰,不用“語句”
“expression” 是一個單純的運算過程扯旷,總是有返回值拯爽。“statement”是執(zhí)行某種操作钧忽,沒有返回值毯炮。沒有“副作用”
“副作用”是指函數(shù)內(nèi)部有與外部的互動,產(chǎn)生運算以外的其他結(jié)果耸黑。函數(shù)要保持獨立桃煎,所有功能返回一個新的值,尤其不得修改外部變量的值大刊。
純函數(shù)是這樣一種函數(shù)为迈,即相同的輸入,永遠會得到相同的輸出,而且沒有任何可觀察的副作用葫辐。
不修改狀態(tài)
函數(shù)式編程使用參數(shù)保存狀態(tài)搜锰,只返回新的值,不修改系統(tǒng)變量耿战。引用透明(Referential transparency)
函數(shù)的運行不依賴外部變量或“狀態(tài)”蛋叼,只依賴輸入?yún)?shù)。只要參數(shù)相同剂陡,引用函數(shù)返回值總是相同的狈涮。
構(gòu)成
高階函數(shù)(higher-order function)
能夠接受一個函數(shù)作為參數(shù)的函數(shù)。函子(Functor)
函子是函數(shù)式編程里最重要的數(shù)據(jù)類型鸭栖,也是基本的運算單位和功能單位歌馍。
函子是指具有map
方法的容器,包含了值和變形關(guān)系纤泵。map
方法將容器里面的每一個值骆姐,映射到另一個容器。即將一個范疇轉(zhuǎn)換成令一個范疇捏题。
構(gòu)成
范疇
這種數(shù)據(jù)模型的要素:
所有成員是一個集合
變形關(guān)系是函數(shù)
- 閉包(Closure)
閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)玻褪,可簡單理解成"定義在一個函數(shù)內(nèi)部的函數(shù)"。當內(nèi)嵌函數(shù)體內(nèi)引用到體外的變量時公荧,將會把定義時涉及到的引用環(huán)境和函數(shù)體打包成一個整體(閉包)返回带射。
類是有行為的數(shù)據(jù),閉包是有數(shù)據(jù)的行為循狰。
閉包是由函數(shù)及其相關(guān)的引用環(huán)境組合而成的實體窟社,即閉包=函數(shù)+引用環(huán)境。
參考
函數(shù)式編程入門教程
函數(shù)式編程初探
學習Javascript閉包(Closure)
lambda
lambda表達式通常在需要一個函數(shù)绪钥,但是又不想費神去命名一個函數(shù)的場合下使用灿里,也就是指匿名函數(shù)。參考
Lambda表達式的本質(zhì)只是一個"語法糖",由編譯器推斷并幫你轉(zhuǎn)換包裝為常規(guī)的代碼,因此你可以使用更少的代碼來實現(xiàn)同樣的功能程腹。
JAVA中的lambda
Java8之前匣吊,傳遞行為的唯一方法就是通過匿名內(nèi)部類。Java中的lamda不是一個匿名內(nèi)部類的語法糖寸潦。在匿名類中色鸳,this
指代的是匿名類本身;而在lambda表達式中见转,this
指代的是lambda表達式所在的這個類命雀。
1.lambda表達式
只有那些僅僅包含一個非實例化抽象方法的接口才能使用lambda表達式。Runnable
接口就是函數(shù)式接口的一個例子斩箫。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Java8默認帶有許多可以直接在代碼中使用的函數(shù)式接口吏砂,它們位于java.util.function
包中撵儿。
2.lambda表達式結(jié)構(gòu)
->
是用來把參數(shù)從函數(shù)體中分離出來的操作符。
在lambda表達式中狐血,我們不需要明確指出參數(shù)類型统倒,javac編譯器會通過上下文自動推斷參數(shù)的類型信息。根據(jù)上下文推斷類型的行為稱為類型推斷
氛雪。
3.方法引用
當需要為一個特定方法創(chuàng)建lambda表達式房匆,比如Function<String, Integer> strToLength = String::length;
,可以用縮寫符號表示。String
是目標引用报亩,::
是定界符浴鸿,length
是目標引用的方法。該方法可以是靜態(tài)或者實例方法弦追。
參考原文
4.實現(xiàn)機制
采用在Java7中新增的動態(tài)啟用
來延遲在運行時的加載策略岳链。當javac編譯代碼時,捕獲代碼中的lambda表達式并生成一個動態(tài)啟用
的調(diào)用地址(稱lambda工廠)劲件。當動態(tài)啟用
被調(diào)用時掸哑,就會向lambda表達式發(fā)生轉(zhuǎn)換的地方返回一個函數(shù)式接口的實例。
JAVA中的Stream
Stream是Java 8 提供的高效操作集合類(Collection
)數(shù)據(jù)的API零远。Stream使用一種類似用SQL語句從數(shù)據(jù)庫查詢數(shù)據(jù)的直觀方式來提供一種對JAVA集合運算和表達的高階抽象苗分。
-
與
Collection
對比
Java8運行開發(fā)者使用stream
方法基于Collection集合創(chuàng)建一個Stream管道。Stream采用內(nèi)部迭代牵辣。
Collection
與Stream
處理集合方式的不同:
Collection與Stream處理集合方式的不同 懶加載
Stream不會儲存數(shù)據(jù)摔癣,懶加載(只有在被使用到時才會執(zhí)行計算)。Stream表達式在被末端操作
方法調(diào)用之前不會被賦值計算纬向。
-
過渡操作
:從已存在的stream上產(chǎn)生另一個新的stream的函數(shù)择浊,比如filter
,map
,sorted
等 -
末端操作
:從stream上產(chǎn)生一個非stream結(jié)果的函數(shù),比如collect(toList())
,forEach
,count
,get
等