JAVA 8 Lambda運算式-Lambda Expressions,lambda-lambda
Lambda運算式介紹
Lambda運算式是在java規範提案JSR 335中定義的,Java 8 中引入了Lambda運算式,並被認為是Java 8最大的新特性,Lambda運算式促進了函數式編程,簡化了Java編程開發。
背景知識匿名內部類
在Java中,匿名內部類一般適用於那些在Java應用中只會出現一次的實作類別,舉個例子,在標準的Swing或JavaFX應用中,有很多鍵盤和滑鼠的事件處理常式,一般情況下,你不需要寫一個單獨的事件處理類,而是使用如下方式(有Swing編程經驗的應該很熟悉吧):
JButton testButton = new JButton("Test Button"); testButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { System.out.println("Click Detected by Anon Class"); } });
不這樣做的話,你需要針對每一個事件寫一個單獨的ActionListener介面的實作類別,這樣的代碼並不優雅,因為僅僅為了定義一個方法就需要附加寫一大堆的代碼。通常,哪裡需要,就在哪裡建立對應的匿名內部類,這樣的代碼可讀性會更強。
Functional Interfaces函數式介面
首選,我們來觀察下上面提到的ActionListener介面的定義,如下:
package java.awt.event;import java.util.EventListener;public interface ActionListener extends EventListener { /** * Invoked when an action occurs. */ public void actionPerformed(ActionEvent e);}
在上面的代碼中,只定義了一個方法,在Java 8中,像這樣的介面被稱為“functional interface”。通常在Java中,我們經常使用匿名內部類來實現函數式介面,這是一種很常見的使用模式;
另外,在JDK中,除了ActionListener介面外,類似的還有Runnable和Comparator介面。
Lambda運算式文法
Lambda運算式的文法形式如下:
parameter -> expression body
主要組成:參數列表 + 箭頭 + 運算式體,如 (int x, int y) -> x + y
其中,運算式體可以是一條運算式,也可以是一個語句塊(多條代碼語句);
Lambda運算式具有如下特徵:
- 【可選】型別宣告:參數的類型不需要聲明,編譯器可以根據參數值推斷出其類型;
- 【可選】括弧:單個參數的話,不需要用圓括弧包圍參數,當然,對於多個參數或無參數的話,括弧是需要的;
- 【可選】花括弧:如果運算式主體只有一條語句的話,不需要用花括弧包圍,當然,對於多條語句,花括弧是需要的;
- 【可選】return關鍵字:如果運算式主體是單一運算式,return關鍵字可以不寫,編譯器可以自動返回該值,當然,如果寫了return,則需要加上花括弧;
舉個例子:
package lambda;/** * LambdaTest * * @author Pi Chen * @version V1.0.0, 2016年9月19日 * @see * @since V1.0.0 */public class LambdaTest{ public static void main(String args[]) { LambdaTest tester = new LambdaTest(); // 有參數類型 MathOperation addition = (int a, int b) -> a + b; // 無參數類型 MathOperation subtraction = (a, b) -> a - b; // 有花括弧,有return關鍵字 MathOperation multiplication = (int a, int b) -> { return a * b; }; // 無花括弧,無return關鍵字,單一運算式情況 MathOperation division = (int a, int b) -> a / b; // MathOperation調用樣本 System.out.println("10 + 5 = " + tester.operate(10, 5, addition)); System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction)); System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication)); System.out.println("10 / 5 = " + tester.operate(10, 5, division)); // 有括弧 GreetingService greetService1 = message -> System.out.println("Hello " + message); // 無括弧,單個參數情況 GreetingService greetService2 = (message) -> System.out.println("Hello " + message); // GreetingService調用樣本 greetService1.sayMessage("Mahesh"); greetService2.sayMessage("Suresh"); //有括弧, 無參情況 Runnable runTest = () -> System.out.println("Running"); //Runnable調用樣本 runTest.run(); } // 內部介面 interface MathOperation { int operation(int a, int b); } interface GreetingService { void sayMessage(String message); } interface Runnable { void run(); } private int operate(int a, int b, MathOperation mathOperation) { return mathOperation.operation(a, b); }}
關鍵點說明:
- Lambda運算式主要用於定義一個函數式介面(functional interface:一個只包含一個方法的介面)的內聯實現,在上面的例子中,我們使用了各種類型的Lambda運算式來實現MathOperation介面的operation方法,接著又實現了GreetingService介面的sayMessage方法,Runnable介面的run方法;
- Lambda運算式消除了匿名類的使用並且賦予Java簡單且強大的函數式編程能力;
參考資料
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html#overview
https://www.tutorialspoint.com/java8/java8_lambda_expressions.htm