Java的Lambda表達式
阿新 • • 發佈:2018-06-16
構造 jdk implement 想想 tar con The wan 問題
Java的Lambda表達式
1. 什麽是Lambda表達式
簡單的說,Lambda表達式就是匿名方法。Lambda表達式讓程序員能夠使用更加簡潔的代碼,但是同樣也使代碼的可讀性比較差。
Lambda表達式也叫做匿名方法或者閉包。
2. 和匿名內部類做對比
Lambda是匿名方法,這個時候我們會想想到匿名內部類,我們來回想一下匿名內部類的用法,比如下面的代碼就是使用匿名內部類實現了一個線程。
public class Test {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("線程:" + Thread.currentThread().getName());
}
});
t.start();
}
}
我們一般的做法是寫一個Runnable接口的實現類,然後new一個實現類再傳給Thread的構造器。如下:
public class Test {
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread t = new Thread(myThread);
t.start();
}
static class MyThread implements Runnable {
@Override
public void run() {
System.out.println("線程:" + Thread.currentThread().getName());
}
}
}
可以看到使用匿名內部類的話就省略了新建Runnable接口的實現類這一步驟。
3. 使用Lambda表達式
上面使用匿名內部類的寫法,如果使用Lambda表達式可以寫成下面這樣:
public class Test {
public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("線程:" + Thread.currentThread().getName());
});
t.start();
}
}
這樣有一個問題,如果接口裏面有多個方法,那麽Lambda表達式怎麽知道實現的是哪個方法呢?我們通過代碼測試一下:
package com.wangjun.othersOfJava;
public class LambdaTest {
public static void main(String[] args) {
Animal a = () -> { // 編譯報錯:The target type of this expression must be a functional interface
System.out.println("狗狗吃飯");
};
a.eat();
}
interface Animal {
public void eat();
public void duty();
}
}
可以看到編譯報錯,這個提到一個functional interface,就是函數式接口。函數式接口就是只有一個抽象方法的接口。這樣,就不難理解了,原來Lambda表達式只支持函數式接口。
4. Lambda表達式使用的幾種方式
package com.wangjun.othersOfJava;
public class LambdaTest {
public static void main(String[] args) {
// 帶類型
Animal a1 = (String str) -> {
System.out.println("狗狗吃飯:" + str);
};
// 不帶類型
Animal a2 = (str) -> {
System.out.println("狗狗吃飯:" + str);
};
// 不帶括號
Animal a3 = str -> {
System.out.println("狗狗吃飯:" + str);
};
// 不帶大括號
Animal a4 = str -> System.out.println("狗狗吃飯:" + str);
a1.eat("火腿腸");
a2.eat("牛肉");
a3.eat("面條");
a4.eat("米飯");
// 使用return返回
Person p1 = () -> {
return "老師的職責:教書育人!";
};
// 直接返回
Person p2 = () -> "醫生的職責:救死扶傷!";
System.out.println(p1.duty());
System.out.println(p2.duty());
}
// 沒有返回值
interface Animal {
public void eat(String str);
}
// 有返回值
interface Person {
public String duty();
}
}
4. Java的雙冒號表達式
JDK8中有雙冒號的用法,就是把方法當做參數傳到stream內部,使stream的每個元素都傳入到該方法裏面執行一下。下面通過遍歷一個List來說明一下雙冒號和Lambda表達式使用方式的不同。
package com.wangjun.othersOfJava;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class LambdaTest {
public static void printStr(String str) {
System.out.println(str);
}
public static void main(String[] args) {
List<String> list = Arrays.asList("aaa","bbb","ccc");
// 1.通常的遍歷方式
for(String str: list) {
LambdaTest.printStr(str);
}
// 2.使用Lambda表達式遍歷
list.forEach(str -> {
LambdaTest.printStr(str);
});
// 3.使用::遍歷
list.forEach(LambdaTest::printStr);
// 下面的方法和上面等價,使用的是函數式編程
Consumer<String> methodParam = LambdaTest::printStr; //方法參數
list.forEach(x -> methodParam.accept(x));//方法執行accept
}
}
Java的Lambda表達式