Java8 Lambda 語法結構、方法引用

什麼是Lambda表達式

Lambda表達式可以看做是一個匿名方法。將一個Lambda表達式做爲參數傳遞給方法,行爲參數化,就實現了函數式編程。
在沒有Lambda之前,要實現函數式編程就需要使用匿名類,如果用Lambda會使得代碼更加簡潔、清晰。

舉個例子:
如果要實現傳遞方法的方式實現加法和減法,可以使用下面匿名類的寫法:

  public class Demo0 {

    //兩個參數的運算
    interface MathOperation {
        double operation(double a, double b);
    }

    public static void main(String[] args) {
        //加法
        MathOperation add=new MathOperation() {
            @Override
            public double operation(double a, double b) {
                return a+b;
            }
        };

        //減法
        MathOperation sub=new MathOperation() {
            @Override
            public double operation(double a, double b) {
                return a-+b;
            }
        };
        System.out.println("20+10:" + add.operation(20, 10));
        System.out.println("20-10:" + sub.operation(20, 10));
    }
}

如果用Lambda表達式實現,可以寫作下面的方式:

   public class Demo1 {

    //兩個參數的運算
    interface MathOperation {
        double operation(double a, double b);
    }

    public static void main(String[] args) {

        //加法
        MathOperation add = (double a, double b) -> a + b;

        //減法
        MathOperation sub = (a, b) -> a - b;

        System.out.println("20+10:" + add.operation(20, 10));
        System.out.println("20-10:" + sub.operation(20, 10));
    }
}

這裏將內部類的變爲了Lambda表達式,簡化了代碼。

基礎語法結構

Lambda的表達式結構如下:

(variable)->action
  1. variable:方法的變量名稱,可以有多個變量,如果只有一個變量,可以將小括號省略。
  2. action:是方法體,是自己寫的代碼邏輯的部分。可以是一行代碼或者多行代碼,如果只有一行代碼,可以不要花括號,如果是多行代碼,需要用花括號括起來。
  3. -> : 這個符號用於將變量和方法體分割開來。

舉例

public class Demo1 {

    //沒有參數的運算
    interface NoParamOperation {
        double operation();
    }

    //一個參數的運算
    interface SingleParamOperation {
        int operation(int a);
    }

    //兩個參數的運算
    interface MathOperation {
        double operation(double a, double b);
    }

    public static void main(String[] args) {

        //======幾種Lambda表達式的寫法=============

        //得到PI值(沒有參數,直接返回)
        NoParamOperation pi = () -> Math.PI;

        //得到自然常數 (沒有參數,直接返回,如果有花括號,要寫上顯式的加上return)
        NoParamOperation e = () -> {
            return Math.E;
        };

        //求平方(如果參數是一個,可以省略小括號)
        SingleParamOperation square = a -> a * a;

        //求立方(可以指定參數的類型,如果沒有編譯器會自動推算)
        SingleParamOperation cubic = (int a) -> a * a * a;

        //加法(如果多個參數,就必須添加上小括號)
        MathOperation add = (double a, double b) -> a + b;

        //減法(多個參數,也可以不指定參數的數據類型)
        MathOperation sub = (a, b) -> a - b;

        //乘法(一行代碼,函數體上也可以寫上花括號)
        MathOperation mult = (double a, double b) -> {
            return a * b;
        };

        //除法(如果函數體有多行,就必須有花括號)
        MathOperation div = (a, b) -> {
            if (b != 0) {
                return a / b;
            } else {
                return 0;
            }
        };
        
        System.out.println("PI的值" + pi.operation());
        System.out.println("自然常數E的值:" + e.operation());

        System.out.println("10的平方:" + square.operation(10));
        System.out.println("10的立方:" + cubic.operation(10));

        System.out.println("20+10:" + add.operation(20, 10));
        System.out.println("20-10:" + sub.operation(20, 10));
        System.out.println("20*10:" + mult.operation(20, 10));
        System.out.println("20/10:" + div.operation(20, 10));
    }
}

更簡單的一種表示方式

方法引用是Lambda表達式的一種簡寫,格式爲:

ObjectRef::methodName
  1. ObjectRef可以是類名、實例名。
  2. :: 符號是方法引用符號。
  3. methodName 是引用的方法名。

有三種方法引用類型:靜態方法引用、實例方法引用、構造方法引用

1、靜態方法引用
public class Demo2 {
    //兩個參數的運算
    interface MathOperation {
        double operation(String format, double a, double b);
    }

    static double formatPrint(String format, double a, double b) {
        double r = a + b;
        System.out.format(format, r);
        return r;
    }

    public static void main(String[] args) {
        //內部類方式,方法中只調用了一個靜態方法formatPrint
        MathOperation add = new MathOperation() {
            @Override
            public double operation(String format, double a, double b) {
                return Demo2.formatPrint(format, a, b);
            }
        };

        //Lambda方式,調用了靜態方法
        MathOperation add1 = (f, a, b) -> Demo2.formatPrint(f, a, b);

        //靜態方法引用方式,代碼更緊湊簡潔
        MathOperation add2 = Demo2::formatPrint;

        System.out.println(add.operation("內部類方式:%f", 20, 10));
        System.out.println(add1.operation("Lambda方式:%f", 20, 10));
        System.out.println(add2.operation("方法引用方式:%f", 20, 10));
    }
}
2、實例方法引用

如果方法中是調用某一個對象的方法,可以簡寫爲方法引用的方式。

public class Demo3 {

    //這裏將方法放到一個類中
    static class Helper {
        public double formatPrint(String format, double a, double b) {
            double r = a + b;
            System.out.format(format, r);
            return r;
        }
    }

    //兩個參數的運算
    interface MathOperation {
        double operation(String format, double a, double b);
    }

    public static void main(String[] args) {
        Helper helper = new Helper();

        //匿名類的方式,方法中調用了helper對象的一個方法。
        MathOperation add1 = new MathOperation() {
            @Override
            public double operation(String format, double a, double b) {
                return helper.formatPrint(format, a, b);
            }
        };

        //Lambda方式,方法體內只是調用一個對象的方法。
        MathOperation add2 =(f,a,b)-> helper.formatPrint(f,a,b);

        //這個時候,就可以簡寫爲方法引用
        MathOperation add3 = helper::formatPrint;

        add1.operation("匿名類的方式:%f\n", 20, 10);
        add2.operation("Lambda方式:%f\n", 20, 10);
        add3.operation("方法引用方式:%f\n", 20, 10);
    }
}
3、構造方法引用

當接口的方法裏操作是實例化一個對象時,比如下面例子裏,只是new 一個對象,對應的Lambda表達式可以簡化爲構造方法引用方式。

舉例:

public class Demo5 {

    //計算器類
    static class Calculator{
        //計算機類的構造函數
        public Calculator(String name)
        {
            this.name=name;
        }

        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
 
    //計算器接口,有一個創建計算器的方法
    interface ICalculator {
        Calculator create(String name);
    }

    public static void main(String[] args) {
        //第1種方式:內部類方式創建電腦對象和中國算盤對象
       ICalculator pc=new ICalculator() {
            @Override
            public Calculator create(String name) {
                return new Calculator("電腦");
            }
        };        

        //第2種方式:用Lambda表達式創建
        Demo4.ICalculator pc2=(name)-> new Demo4.Pc("電腦");

        //第3種方式:用方法引用方式進一步簡化Lambda表達式。
        Demo4.ICalculator pc3=Demo4.Pc::new;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章