1. 程式人生 > >Java SE JDK8新功能--23.Lambda表示式

Java SE JDK8新功能--23.Lambda表示式

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);  // 方法的呼叫
    }
}