Java類型系列--Lambda表達式

其他網址

Java中Lambda表達式的使用 - Franson - 博客園

簡介

        Lambda表達式的本質只是一個"語法糖",由編譯器推斷並幫你轉換包裝爲常規的代碼,因此你可以使用更少的代碼來實現同樣的功能。本人建議不要亂用,因爲這就和某些很高級的黑客寫的代碼一樣,簡潔,難懂,難以調試,維護人員想罵娘.)

        Lambda表達式是Java SE 8中一個重要的新特性。lambda表達式允許你通過表達式來代替功能接口。 lambda表達式就和方法一樣,它提供了一個正常的參數列表和一個使用這些參數的主體(body,可以是一個表達式或一個代碼塊)。

        Lambda表達式還增強了集合庫。 Java SE 8添加了2個對集合數據進行批量操作的包: java.util.function 包以及java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了許多額外的功能。 總的來說,lambda表達式和 stream 是自Java語言添加泛型(Generics)和註解(annotation)以來最大的變化。 

Lambda表達式的語法

(parameters) -> expression   或(parameters) ->{ statements; }

lambda表達式的重要特徵

  • 可選類型聲明:不需要聲明參數類型,編譯器可以統一識別參數值。
  • 可選的參數圓括號:一個參數無需定義圓括號,但多個參數需要定義圓括號。
  • 可選的大括號:若主體包含了一個語句,就不需要使用大括號。例: () -> Sysout.out.println("Test");
  • 可選的返回關鍵字:若主體只有一個表達式返回值則編譯器會自動返回值,大括號需指定明表達式返回了一個數值。

Lambda 表達式的簡單例子 

// 1. 不需要參數,返回值爲 5  
() -> 5  
  
// 2. 接收一個參數(數字類型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2個參數(數字),並返回他們的差值  
(x, y) -> x – y  
  
// 4. 接收2個int型整數,返回他們的和  
(int x, int y) -> x + y  
  
// 5. 接受一個 string 對象,並在控制檯打印,不返回任何值(看起來像是返回void)  
(String s) -> System.out.print(s)

語法格式

左側:Lambda 表達式的參數列表
右側:Lambda 表達式中所需要執行的功能 (Lambda體)

語法格式一:無參數,無返回值
    () -> Sysout.out.println("Test");

語法格式二:有一個參數,並且無返回值
    (X)-> Sysout.out.println(x);

語法格式三:如果有一個參數括號可以不寫
    X-> Sysout.out.println(x);
語法格式四:有兩個以上的參數,有返回值,並且Lambda體中有多條語句 語法體中需要用{}
    Comparator<Integer> comparator = (o1, o2) -> {
        System.out.println("Test");
        return Integer.compare(o1, o2);
    };
語法格式五:Lambda體中只用一條語句,return和{}可以省略不寫
    Comparator<Integer> comparator = (o1, o2)->Integer.compare(o1, o2);
語法格式六:表達式的參數列表的數據類型可以省略不寫,JVM編譯器通過上下文推斷出數據類型
    (x ,y ) ->Integer.compare(x ,y)

 變量和作用域

1.Lambda 表達式只能引用標記了 final 的外層局部變量。即不能在 lambda 內部修改定義在域外的局部變量,否則編譯報錯
2.Lambda 表達式的局部變量可以不用聲明爲 final,但是必須不可被後面的代碼修改(即隱性的具有 final 的語義)
3.Lambda 表達式中不允許聲明一個與局部變量同名的參數或者局部變量。

對接口的要求

雖然使用 Lambda 表達式可以對某些接口進行簡單的實現,但並不是所有的接口都可以使用 Lambda 表達式來實現。Lambda 規定接口中只能有一個需要被實現的方法,不是規定接口中只能有一個方法

jdk 8 中有另一個新特性:default, 被 default 修飾的方法會有默認實現,不是必須被實現的方法,所以不影響 Lambda 表達式的使用。

@FunctionalInterface:用來修飾函數式接口,要求接口中的抽象方法只有一個。 此註解往往和 lambda 表達式一起出現。

實例

其他網址

Java8學習筆記(一)--Lambda表達式 - 舒山 - 博客園
Java中Lambda表達式的使用 - Franson - 博客園

函數式接口(無參數無返回值)

package org.example.a;

@FunctionalInterface
interface Interface {
    void run();
}

public class Demo{
    public static void main(String[] args) {
        Interface params = new Interface() {
            @Override
            public void run() {
                System.out.println("Anonymous Internal Class: ");
            }
        };

        Interface params1 = () -> System.out.println("Lambda: ");

        params.run();
        params1.run();
    }
}

 執行結果

Anonymous Internal Class: 
Lambda: 

函數式接口(有參數無返回值)

package org.example.a;

@FunctionalInterface
interface Interface {
    void run(String s);
}

public class Demo{
    public static void main(String[] args) {
        Interface params = new Interface() {
            @Override
            public void run(String s) {
                System.out.println("Anonymous Internal Class: " + s);
            }
        };

        Interface params1 = (s) -> System.out.println("Lambda: " + s);

        params.run("hello");
        params1.run("hi");
    }
}

執行結果

Anonymous Internal Class: hello
Lambda: hi 

函數式接口(有參數有返回值)

package org.example.a;

@FunctionalInterface
interface Interface {
    String run(String s);
}

public class Demo{
    public static void main(String[] args) {
        Interface params = new Interface() {
            @Override
            public String run(String s) {
                System.out.println("Anonymous Internal Class: " + s);
                return "abc";
            }
        };

        Interface params1 = (s) -> {
            System.out.println("Lambda: " + s);
            return "def";
        };

        System.out.println(params.run("hello"));
        System.out.println(params1.run("hi"));
    }
}

執行結果

Anonymous Internal Class: hello
abc
Lambda: hi
def 

遍歷集合

package org.example.a;

import java.util.ArrayList;
import java.util.List;

public class Demo{
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");

        //以前的循環方式
        for (String string : list) {
            System.out.println(string);
        }

        //使用lambda表達式輸出list中的每個值
        list.forEach(c->{
            System.out.println(c);
        });

        // 在 Java 8 中使用雙冒號操作符(double colon operator)。也屬於lamda表達式
        list.forEach(System.out::println);
    }
}

執行結果

aaa
bbb
aaa
bbb
aaa
bbb

 創建線程

package org.example.a;

public class Demo{
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Anonymous Internal Class !");
            }
        }).start();

        new Thread(() -> System.out.println("Lambda !")).start();
    }
}

 執行結果

Anonymous Internal Class !
Lambda !

排序

package org.example.a;

import java.util.Arrays;
import java.util.Comparator;

public class Demo{
    public static void main(String[] args) {
        String[] players = {"Rafael Nadal", "Novak Djokovic", "Stanislas Wawrinka"};
        
        Arrays.sort(players, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return (o1.compareTo(o2));
            }
        });

//        Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));
//        Arrays.sort(players, sortByName);
        
//        Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));
        
        for(String string:players){
            System.out.println(string);
        }
    }
}

執行結果(換成註釋掉的兩種任意一種都是一樣的)

Novak Djokovic
Rafael Nadal
Stanislas Wawrinka

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章