先來個小例子看下,有個直觀的瞭解。
//1.首先,要定義一個函數式接口
//即Functional Interface,就是隻有一個抽象方法的接口。
public interface Func {
double func(double x);
}
//2.測試
public void testLambda() {
//定義一個數學函數:f(x) = x^2
//如果用lambda表達式,則寫法如下:
Func f1 = (x)->x*x;
//同理,定義一個數學函數:f(x) = x^3
Func f2 = (x)->x*x*x;
//如果用匿名內部類的話,寫法如下:
// Func f1 = new Func() {
// public double func(double x) {
// return x*x;
// }
// }
//定義自變量
double x = 8;
//相當於y = f(x)
double y1 = f1.func(x);
double y2 = f2.func(x);
//輸出結果
System.out.println(y1);
System.out.println(y2);
}
從上面看出,lambda表達式首先需要一個函數式接口,然後採用lambda實現該接口(等價於匿名內部類)。實現形式有兩種:
(傳入參數) -> 你要做的事情
//或者
(傳入參數) -> { 你要做的事情 }
注意的是,這裏lambda和匿名內部類一樣,不能對外部變量變量進行修改(原話是Local variable defined in an enclosing scope must be final or effectively final,也就是說,如果使用閉合作用域中的變量,那麼這個變量必須是final或事實final,說白了,不能修改),如下,PI作爲一個參數可以在lambda中使用,但是不能在其中修改:
@Test
public void testLambda2() {
double PI = 3.1415926535897932384626;
//求圓的面積公式
Func S = (r) -> PI * r * r;
//求解過程
double x = 10.0;
double y = S.func(x);
System.out.println("y = " + y);
}
儘管使用上,lambda與匿名內部類相似,然而,lambda與匿名內部類有一些深層次的差異:
1. 匿名類的 this 關鍵字指向匿名類,而lambda表達式的 this 關鍵字指向包圍lambda表達式的類。
2. Java編譯器將lambda表達式編譯成類的私有方法。
下面來點稍微高級的用法:
/**
* 求解一個list中的所有數據的平方
*/
@Test
public void testLambda1() {
//定義一個Double型的List
List<Double> list = Arrays.asList(1.0, 2.0, 3.0, 4.0, 5.0);
//定義一個存放結果的List
List<Double> list2 = new ArrayList<>();
//將list中每個數求平方,然後放到list2中
//這裏的forEach方法是JDK1.8中引入的
list.forEach((a)->list2.add(a*a));
//打印結果
System.out.println(list);
System.out.println(list2);
}
排序中採用lambda代替匿名內部類
@Test
public void testLambda3() {
//定義測試list
List<Double> list = Arrays.asList(1.0, 9.0, 4.0, 11.0, 33.0, 24.0, 12.0, 2.0, 3.0, 4.0, 5.0);
//調用工具類Collections的排序方法,傳入一個排序規則
//這裏的lambda說白了就是實現了Comparator的匿名內部類
Collections.sort(list, (x, y) -> (int)Math.ceil(x - y));
//輸出結果
System.out.println(list);
}
這寫用法看起來很炫,有些也確實很實用,但是不知道這種語法能不能普及