Java 中的 Lambda 表示式

城北有個混子發表於2020-10-27

Lambda表示式

  Lambda 表示式是 JDK1.8 的一個新特性,又稱特殊的匿名內部類,可以取代大部分的匿名內部類,語法更簡潔,可以寫出更優雅的 Java 程式碼,可以極大地優化程式碼結構。

  Lambda 表示式不會生成單獨的內部類檔案,但匿名內部類會。

 


Lambda表示式特性

  ★ Lambda 表示式沒有顯示的方法名。

  ★ Lambda 表示式很像一個函式,具有引數列表、函式體、返回型別、異常,但沒有函式名。

  ★ Lambda 表示式可以作為方法的引數,也可以作為變數儲存。

  ★ Lambda 表示式的程式碼更加簡潔和精確。

 


Lambda表示式的定義

基本語法:

  <函式式介面>  <變數名> = (引數1, 引數2...) -> {

    //方法體

  };

  或

  <函式式介面>  <變數名> = (引數1, 引數2...) -> 表示式;

注意事項:

  ✔ Lambda 表示式由三部分構成:引數列表、箭頭(->)、Lambda 體。

  ✔ Lambda 體,可以是一個表示式,也可以是一個語句塊。

  ✔ Lambda 體,表示式中不能加入 return 語句,因為在表示式中已經隱含了 return 語句;但是,語句塊中沒有隱含,需要使用 return 語句。

  ✔ Lambda 表示式並不是對所有介面都可以實現,介面需要滿足一個條件才能被Lambda 表示式實現:Lambda 規定介面中只能有一個需要被實現的方法。注意,並不是規定介面中只能有一個方法。

 

特別提醒:

    jdk1.8 中的另一個新特性:default,被 default 修飾的方法會有預設實現,不是必須被實現的方法。在實現Lambda 表示式的時候需注意。

 


Lambda 表示式的使用

1.無參,有返回值

@FunctionalInterface        
public interface LambdaTest {
    // 無參,有返回值
    int method();
}
public class test {

    public static void main(String[] args) {
        
        LambdaTest test = ()-> 20;
        
        int result = test.method();
        
        System.out.println(result);
    }
}

@FunctionalInterface註解:

  修飾函式式介面的,要求介面中的抽象方法只有一個。這個註解往往和 lambda 表示式一起出現。

2.無參,無返回值

@FunctionalInterface        
public interface LambdaTest {
    // 無參,無返回值
    void method();
}
public class test {

    public static void main(String[] args) {
        
        LambdaTest test = () -> {};
        
        test.method();
        
    }
}

3.單參,有返回值

@FunctionalInterface        
public interface LambdaTest {
    // 單參,有返回值
    int method(int a);
}
public class test {

    public static void main(String[] args) {
        
        // 表示式形式
        LambdaTest test = a -> a+10;
        
        System.out.println(test.method(10));
        
        // 程式碼塊形式
        LambdaTest test2 = a -> {
            return a+10;
        };
        
        System.out.println(test2.method(10));
    }
}

4.多參,有返回值

@FunctionalInterface        
public interface LambdaTest {
    // 多參,有返回值
    int method(String a, String b);
}
public class test {

    public static void main(String[] args) {
        
        // 表示式形式
        LambdaTest test = (a, b) -> a.length() - b.length();
        
        System.out.println(test.method("abb", "bbccdd"));
        
        // 程式碼塊形式
        LambdaTest test2 = (a, b) -> {
            return a.length() - b.length();
        };
        
        System.out.println(test2.method("abb", "bbccdd"));
    }
}

表示式使用技巧總結

  ★ 形參列表的資料型別會自動判斷。

  ★ 如果形參列表為空,只需保留()。

  ★ 如果形參只有一個,()可以省略,只需要引數的名稱即可。

  ★ 如果執行語句只有一句,且無返回值,則{}可省略;如果有返回值,若想省略{},則必須同時省略return,且執行語句也必須保證只有一句。

 


Lambda 表示式應用

方法引用

  有時候我們不是必須要自己重寫某個匿名內部類的方法,我們可以可以利用 lambda表示式的介面快速指向一個已經被實現的方法。

引用語法:

方法歸屬者::方法名

靜態方法的歸屬者為類名,普通方法歸屬者為物件。

常見形式:

物件 :: 例項方法
  類 :: 靜態方法
  類 :: 例項方法
  類 :: new

引用要求:

  ① 引數數量和型別要與介面中定義的一致。

  ② 返回值型別要與介面中定義的一致。

程式碼示例:

public class MethodReferences {
    public static void main(String[] args) {
        // 1.物件::例項方法
        Consumer<String> consumer = s->System.out.println(s);
        consumer.accept("hello");
        
        Consumer<String> consumer2 = System.out::println;
        consumer2.accept("world");
        
        // 2.類::靜態方法
        Comparator<Integer> com = (o1, o2)->Integer.compare(o1, o2);
        Comparator<Integer> com2 = Integer::compare;
            
        // 3.類::例項方法
        Function<String, String> function = e->e.toUpperCase();
        Function<String, String> function2 = String::toUpperCase;
        System.out.println(function2.apply("hello"));
        
        // 4.類::new
        Supplier<String> supplier = ()->new String();
        Supplier<String> supplier2 = String::new;
        System.out.println(supplier2.toString());
    }
}

 


建立執行緒

public class TestLambda {
    public static void main(String[] args) {
        // 匿名內部類
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                System.out.println("子程式執行。。。");
            }
        };
        
        // Lambda表示式
        Runnable runnable2 = ()->System.out.println("子程式執行2。。。");
        new Thread(runnable2).start();
new Thread(()->System.out.println("子程式執行3。。。")).start(); } }

 


集合操作

  可以呼叫集合的 public void forEach(Consumer<? super E> action) 方法,通過 Lambda 表示式的方式遍歷集合中的元素。Consumer 介面是 jdk 為我們提供的一個函式式介面。

public class test {

    // 集合遍歷
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();

        Collections.addAll(list, 4, 3, 9, 0, 5);

        // 方法引用
        list.forEach(System.out::println);

        // Lambda表示式
        list.forEach(element -> {
            if (element % 2 == 0) {
                System.out.println(element);
            }
        });
    }
}
public class test {

    // 集合排序
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();

        Collections.addAll(list, 4, 3, 9, 0, 5);

        // 匿名內部類
        list.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
            
        });        

        // lambda表示式
        list.sort((o1,o2)->o1-o2);
        
        list.forEach(System.out::println);
    }
}

 

相關文章