簡介:
Lambda表達式的使用場景非常廣泛,主要包括函數式編程、集合操作、排序、線程編程、GUI事件處理、數據處理、Web開發等。
函數式編程:Lambda表達式是函數式編程的重要特性,可以用于替代傳統的匿名內部類,簡化代碼,提高可讀性。
集合操作:Lambda表達式可以與集合操作方法(如forEach、filter、map、reduce)結合使用,對集合中的元素進行遍歷、篩選、映射、聚合等操作。
排序:Lambda表達式可以用于自定義的排序功能,通過傳遞不同的比較規則實現對集合中元素的排序。
線程編程:Lambda表達式可以用于簡化線程編程中的代碼,例如使用Lambda表達式創建Runnable對象、使用Lambda表達式實現函數式接口來處理線程任務等。
GUI事件處理:Lambda表達式可以用于簡化GUI事件處理代碼,例如為按鈕、菜單等組件注冊事件監聽器。
數據處理:Lambda表達式可以用于對大數據集進行處理,如統計、過濾、轉換等,其并行處理的能力可以提高數據處理的效率。
Web開發:Lambda表達式可以用于簡化Web開發中的重復性代碼,例如通過Lambda表達式實現控制器、過濾器、攔截器等。
1) Lambda表達式僅能放入如下代碼:預定義使用了 @Functional 注釋的函數式接口,自帶一個抽象函數的方法,或者SAM(Single Abstract Method 單個抽象方法)類型。這些稱為lambda表達式的目標類型,可以用作返回類型,或lambda目標代碼的參數。例如,若一個方法接收Runnable、Comparable或者 Callable 接口,都有單個抽象方法,可以傳入lambda表達式。類似的,如果一個方法接受聲明于 java.util.function 包內的接口,例如 Predicate、Function、Consumer 或 Supplier,那么可以向其傳lambda表達式。
2) lambda表達式內可以使用方法引用,僅當該方法不修改lambda表達式提供的參數。本例中的lambda表達式可以換為方法引用,因為這僅是一個參數相同的簡單方法調用。
list.forEach(n -> System.out.println(n));
list.forEach(System.out::println); // 使用方法引用
然而,若對參數有任何修改,則不能使用方法引用,而需鍵入完整地lambda表達式,如下所示:
list.forEach((String s) -> System.out.println("*" + s + "*"));
事實上,可以省略這里的lambda參數的類型聲明,編譯器可以從列表的類屬性推測出來。
3)lambda內部可以使用靜態、非靜態和局部變量,這稱為lambda內的變量捕獲。
4)Lambda表達式在Java中又稱為閉包或匿名函數,所以如果有同事把它叫閉包的時候,不用驚訝。
5)Lambda方法在編譯器內部被翻譯成私有方法,并派發 invokedynamic 字節碼指令來進行調用。可以使用JDK中的 javap 工具來反編譯class文件。使用 javap -p 或 javap -c -v 命令來看一看lambda表達式生成的字節碼。大致應該長這樣:
private static java.lang.Object lambda$0(java.lang.String);
6)lambda表達式有個限制,那就是只能引用 final 或 final 局部變量,這就是說不能在lambda內部修改定義在域外的變量。
List<Integer> primes = Arrays.asList(new Integer[]{2, 3,5,7});
int factor = 2;
primes.forEach(element -> { factor++; });
Compile time error : "local variables referenced from a lambda expression must be final or effectively final"
//另外,只是訪問它而不作修改是可以的,如下所示:
List<Integer> primes = Arrays.asList(new Integer[]{2, 3,5,7});
int factor = 2;
primes.forEach(element -> { System.out.println(factor*element); });
1、Lambda表達式概述
Lambda表達式是JDK1.8之后的一種語法,是一個匿名函數,是對匿名函數的簡寫形式,我們可以把 Lambda表達式理解為是一段可以傳遞的代碼(將代碼像數據一樣進行傳遞),可以寫出更簡潔、更靈活的代碼。作為一種更緊湊的代碼風格,使Java的語言表達能力得到了提升;
首先來看一下什么是Lambda表達式:
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;public class MyTest {public static void main(String[] args) {Integer[] ints = {98, 243, 35, 13, 57, 243};List<Integer> list = Arrays.asList(ints); //之前的排序list.sort(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}});System.out.println(list);//[243, 243, 98, 57, 35, 13]//使用Lambda表達式list.sort((o1,o2)->(o1-o2));System.out.println(list);//[13, 35, 57, 98, 243, 243]}
}
通過上面的對比,發現Lambda表達式式書寫起來更為簡潔;
2、Lambda表達式語法
JDK1.8之后引入的一種語法,他的寫法是使用一個
->
符號,箭頭將Lambda表達式分為左右兩部分,左邊寫的是實現的這個接口中的抽象方法中的形參列表,右邊就是對抽象方法的處理;實現的這個接口中的抽象方法中的形參列表 -> 抽象方法的處理
3、具體寫法
因為Lambda表達式的核心就是實現的這個接口中的抽象方法中的形參列表 -> 抽象方法的處理,因此根據形參列表與返回值的不同,Lambda表達式的具體寫法也不相同;
無返回值有形參的抽象方法
public class MyTest1 {public static void main(String[] args) {MyInterface myInterface = new MyInterface() {@Overridepublic void show(int a, int b) {System.out.println(a + b);}};myInterface.show(20, 30);//50//簡寫1:方法名可以自己推斷出來MyInterface myInterface1 = (int a, int b) -> {System.out.println(a + b);};myInterface1.show(20, 40);//60//簡寫2:可以省略形參列表中的形參類型MyInterface myInterface2 = (a, b) -> {System.out.println(a + b);//70};myInterface2.show(20, 50);//簡寫3:如果抽象方法中只有一行代碼,可以省略方法體的大括號,當然,如果不止一行,就不能省略MyInterface myInterface3 = (a, b) -> System.out.println(a + b);myInterface3.show(20, 60);//80}
}
public interface MyInterface {public abstract void show(int a,int b);
}
可以省略方法名,IDEA會幫你自動檢測方法名;
可以省略方法中的形參類型;
如果對抽象方法的實現邏輯只有一行,可以省略方法體的大括號,當然如果不止一行,就不能省略了;
有返回值的抽象方法
public class MyTest2 {public static void main(String[] args) {MyInterface1 test1 = new MyInterface1() {@Overridepublic int test(int a, int b) {return a - b;}};System.out.println(test1.test(90, 8));//82//簡寫1:MyInterface1 test2 = (int a, int b) -> {return a - b;};System.out.println(test2.test(20, 10));//10//簡寫2:MyInterface1 test3 = (a, b) -> {return a - b;};System.out.println(test3.test(30, 10));//20//簡寫3:這個有返回值的方法,不能直接去掉大括號,還需要去掉return關鍵字MyInterface1 test4 = (a, b) -> a - b;System.out.println(test4.test(40, 10));//30}
}
public interface MyInterface1 {public abstract int test(int a,int b);
}
有返回值的方法,如果要去掉大括號,還需要去掉return關鍵字;
有一個形參的抽象方法
public class MyTest3 {public static void main(String[] args) {