最近學到的Lambda表達式基礎知識
- 2019 年 10 月 5 日
- 筆記
前言
只有光頭才能變強。 文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y
中秋去了躺上海,在外灘上打了個卡:

外灘
緊接著學了一下Java的函數式編程,給大家整理了一下,一起學習!
一、Lambda用法
之前寫Optional這個類的時候,簡單說了一下Lambda是怎麼用的,這裡再跟大家一起回顧一下,Lambda的語法是這樣的:

語法
以Lambda語法創建執行緒和匿名內部類創建執行緒的區別(顯然程式碼少了很多!):
public static void main(String[] args) { // 用匿名內部類的方式來創建執行緒 new Thread(new Runnable() { @Override public void run() { System.out.println("公眾號:Java3y---關注我!"); } }); // 使用Lambda來創建執行緒 new Thread(() -> System.out.println("公眾號:Java3y---關注我!")); }
使用Lambda表達式,實際就是創建出該介面的實例對象。

返回一個Runnable對象實例
圖示;Runnable介面來舉例:

以Runnable介面為例
使用Labmda表達式需要函數式編程介面,比如在Runnable介面上我們可以看到@FunctionalInterface
註解(標記著這個介面只有一個抽象方法)

函數式編程介面只有一個抽象方法
1.1 函數式編程介面
從上面的程式碼例子可以看出,我們使用Lambda表達式創建執行緒的時候,並不關心介面名,方法名,參數名。我們只關注他的參數類型,參數個數,返回值。
JDK原生就給我們提供了一些函數式編程介面方便我們去使用,下面是一些常用的介面:

常用的函數式編程介面
簡單說明一下:
- 表格中的一元介面表示只有一個入參,二元介面表示有兩個入參

以BiFunction為例

常用的函數式介面
Demo:
// Consumer 一個入參,無返回值 Consumer<String> consumer = s-> System.out.println(s); consumer.accept("Java3y"); // Supplier 無入參,有返回值 Supplier<String> supplier = () -> "Java4y"; String s = supplier.get(); System.out.println(s); //.....
使用Lambda時,要記住的就兩點:
- Lambda返回的是介面的實例對象
- 有沒有參數、參數有多少個、需不需要有返回值、返回值的類型是什麼—->選擇自己合適的函數式介面
1.2 方法引用
在學Lambda的時候,還可能會發現一種比較奇怪的寫法,例如下面的程式碼:
// 方法引用寫法 Consumer<String> consumer = System.out::println; consumer.accept("Java3y");
如果按正常Lambda的寫法可能是這樣的:
// 普通的Lambda寫法 Consumer<String> consumer = s -> System.out.println(s); consumer.accept("Java3y");
顯然使用方法引用比普通的Lambda表達式又簡潔了一些。
如果函數式介面的實現恰好可以通過調用一個方法來實現,那麼我們可以使用方法引用

函數式介面的實現恰好可以通過調用一個方法來實現
方法引用又分了幾種:
- 靜態方法的方法引用
- 非靜態方法的方法引用
- 構造函數的方法引用
方法引用Demo:
public class Demo { public static void main(String[] args) { // 靜態方法引用--通過類名調用 Consumer<String> consumerStatic = Java3y::MyNameStatic; consumerStatic.accept("3y---static"); //實例方法引用--通過實例調用 Java3y java3y = new Java3y(); Consumer<String> consumer = java3y::myName; consumer.accept("3y---instance"); // 構造方法方法引用--無參數 Supplier<Java3y> supplier = Java3y::new; System.out.println(supplier.get()); } } class Java3y { // 靜態方法 public static void MyNameStatic(String name) { System.out.println(name); } // 實例方法 public void myName(String name) { System.out.println(name); } // 無參構造方法 public Java3y() { } }
結果如下:

結果
最後
Lambda雖然程式碼看起來是簡潔,但是如果複雜的話還是比較難看明白的。
在學習Lambda的時候,首先我們得知道有哪些常用函數式編程介面,這些函數式編程介面的有什麼區別(參數個數、返回值類型)
Lambda表達式返回的是介面對象實例,如果函數式介面的實現恰好可以通過調用一個方法來實現,那麼我們可以使用方法引用來替代Lambda表達式
最後再完整舉個例子:
// Supplier是一個無入參帶返回的值的函數式編程介面 // () -> new Java3y()這整句Lambda表達式,返回的是Supplier介面的實例。從Lambda表達式可以看出無參數,帶返回值 Supplier<Java3y> supplier = () -> new Java3y(); // 由於這個「() -> new Java3y()」Lambda表達式可以通過調用一個方法就實現了,那麼我們可以優化成方法引用 Supplier<Java3y> supplier2 = Java3y::new;