Java SE JDK8新功能--23.Lambda表示式
阿新 • • 發佈:2018-12-14
1、概述
簡介:Lambda表示式是Java SE 8中一個重要的新特性。lambda表示式允許你通過表示式來代替功能介面
格式:()->{}
():介面中抽象方法的引數列表.
-> :分隔符
{}:介面中抽象方法的實現體.
2、Lambda使用條件
使用Lambda表示式必須有介面、且介面中有且僅有一個抽象方法、
或必須有“函式式介面”作為方法的引數
函式式介面:只有一個抽象方法(Object類中的方法除外)的介面是函式式介面
3、Lambda表示式省略規則
1. 小括號內參數的型別可以省略; 2. 如果小括號內有且僅有一個參,則小括號可以省略;如果沒有引數、小括號不能省 3. 如果大括號內有且僅有一個語句,則無論是否有返回值,都可以省略大括號、return關鍵字及語句分號。
4、Runnable介面優化
說明:Runnable介面中有且只有一個抽象方法run、所以是函式式介面、就可以使用Lambda表示式了
演示:
public class ThreadTest { public static void main(String[] args) { // 方案一 : 實現類 // new Thread(new MyRunnable()).start(); // 方案二 : 匿名實現類 (省略了實現類的名稱) new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + " -> run ... " + i); } } }).start(); // 方式三 : Lambda 表示式 (能省則省) // 省略1 : 介面的名稱. // 省略2 : 抽象方法的名稱. // 自動推導 : Thread 類的構造方法. 推匯出函式式介面的名稱為 Runnable, 在根據 Runnable 函式式介面就可以推匯出 `抽象方法` 的名稱. /* 1. () : 表示抽象方法 run 的引數列表. 2. -> : 分隔符. 引數列表 -> 方法體 3. {} : 抽象方法的方法體實現. */ new Thread(() -> { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + " -> run ... " + i); } }).start(); // 主執行緒執行程式碼 ... for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + " -> run ... " + i); } } }
5、Comparator介面優化
說明:Comparator介面中有且僅有一個抽象方法compare、所以可以用Lambda表示式
需求 :對集合中的 Student 物件進行排序. 規則為: 按照年齡從小到大排列.
演示:
public class StudentSortTest { public static void main(String[] args) { // 1. 建立一個集合, 儲存多個 Student 物件 ArrayList<Student> list = new ArrayList<>(); list.add(new Student("張三", 18)); list.add(new Student("李四", 16)); list.add(new Student("王五", 19)); list.add(new Student("趙六", 17)); // 排序 : 函式式介面相關的方法. Collections.sort(list, Comparator函式式介面); // 方式一 : 實現類 Collections.sort(list, new MyComparactor()); // 方式二 : 匿名實現類 Collections.sort(list, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { // 按照年齡從小到大 return o1.getAge() - o2.getAge(); } }); // 方式三 : Lambda 表示式 /* 1. () : 抽象方法的引數列表 2. -> : 分隔符 3. {} : 抽象方法的實現體 */ Collections.sort(list, (Student o1, Student o2) -> { // 按照年齡從小到大 return o1.getAge() - o2.getAge(); }); Collections.sort(list, (o1, o2) -> { return o1.getAge() - o2.getAge(); }); Collections.sort(list, (a, b) -> a.getAge() - b.getAge());//省略後的寫法 // 遍歷 for (Student stu : list) { System.out.println(stu); } } }
6、Lambda無參無返回值
package com.mvcCase.Test;
public interface Cook {
public abstract int eat(int num1, int num2);
}
package com.mvcCase.Test;
public class LambdaTest {
public static void main(String[] args) {
// 呼叫方法, 傳遞 Lambda 表示式
// 請問 : 如果一個方法是介面型別, 那麼其真正需要的是該介面的實現類物件.
// 方式一 : 匿名實現類傳遞引數
keepAlive(new Cook() {
// 方法的定義 :
@Override
public void eat() {
System.out.println("吃飯、匿名實現類");
}
});
// 方式二 : Lambda 表示式
keepAlive(() -> { System.out.println("吃飯、Lambda");});
// 方式三 : 省略原則
keepAlive(() -> System.out.println("吃飯、Lambda簡寫"));
}
// 方法 : 必須使用 `函式式介面` 作為方法的引數型別
public static void keepAlive(Cook cook) {
// 介面呼叫抽象方法, 其真正呼叫的是 `實現類` 的重寫方法.
cook.eat(); // 方法的呼叫
}
}
7、Lambda有參有返回值
package com.mvcCase.Test;
public interface Cook {
public abstract int eat(int num1, int num2);
}
package com.mvcCase.Test;
public class LambdaTest {
public static void main(String[] args) {
// 呼叫方法, 傳遞 Lambda 表示式
// 請問 : 如果一個方法是介面型別, 那麼其真正需要的是該介面的實現類物件.
// 方式一 : 匿名實現類傳遞引數
int sum = keepAlive(10, 10, new Cook() {
// 方法的定義 :
@Override
public int eat(int num1, int num2) {
return num1 + num2;
}
});
System.out.println("總共多少次=" + sum);
// 方式二 : Lambda 表示式
int sum1 = keepAlive(20, 20, (n1, n2) -> { return n1 + n2; });
System.out.println("總共多少次=" + sum1);
// 方式三 : 省略原則
int sum2 = keepAlive(30,30,(a1, a2)->a1+a2);
System.out.println("總共多少次=" + sum2);
}
// 方法 : 必須使用 `函式式介面` 作為方法的引數型別
public static int keepAlive(int num1, int num2, Cook cook) {
// 介面呼叫抽象方法, 其真正呼叫的是 `實現類` 的重寫方法.
return cook.eat(num1, num2); // 方法的呼叫
}
}