天天看點

Java8 Lambda 介紹

lambda是一段可以傳遞的代碼,可以被多次執行。當然,不使用lambda表達式也可以寫出同樣的代碼,對比如下,可以看到lambda的寫法簡潔很多。

lambda文法格式如下,如果一個表達式無法完整表達邏輯,那就就寫成一個代碼塊,用花括号括起。

(參數...) -> [表達式;代碼塊]

示例:

對于隻包含一個抽象方法的接口,就可以通過lambda表達式來建立該接口的對象啦,這種接口就叫做函數式接口。java.util.function包中預定義了好多函數式接口,并且同意标記上了注解【@functionalinterface】。自定義的函數式接口也建議加上這個注解,因為編譯器會檢查該實體,是否隻包含一個抽象方法的,同時也更加清晰可讀。

例如:

這裡的tomap方法接收的輸入參數就是function函數:

方法引用:

構造器引用:

構造器引用會自動适配一個合适的構造函數,例如上面的示例會适配一個入參為一個string類型的構造函數。

在java中原有的閉包:

此處變量i是testclosure方法的内部變量,但是我們在匿名内部函數get中卻傳回了 i;内部變量 i 的生存周期延長了,并且使得變量 i 可以被外部函數所引用,這就是閉包。注意變量 i 必須為final,否則會編譯錯誤。

在lambda中的閉包:

此處 i 不需要定義為final,但是這僅僅是一個文法糖,事實上任何對 i 的value的變更一樣會引起文法錯誤。

lambda表達式都是延遲執行的,如果需要立即執行一段代碼,就沒必要使用lambda表達式了,就好像如果需要立即執行就沒必要使用匿名内部類一樣。lambda表達式可以在另一個線程中執行,可以多次運作,按需運作,在某個正确的時機(事件觸發,算法運作的某個時間點)運作。

例如,常用的log記錄方式如下:

參數會立即計算完成再傳遞給info方法,此時會判斷日志級别,如果符合info輸出才會列印日志,如果為debug等info不輸出的情況,會忽略目前資訊,但是呢參數已經計算過了。做了一次無用功。此時如果改為lambda延遲執行,則不會出現這種無謂的計算。如下:

遲來的特性,哈哈,不過還是帶來了很多便利的。