java Lambda 表示式

2020-09-20 04:00:34

Lambda 介紹

Lambda 表示式,也可稱為閉包,他是推動 java8 釋出的重要特徵。
Lambda 允許把函數作為一個方法引數(函數作為引數傳遞進方法)。
使用 Lambda 表示式可以是程式碼更簡潔緊湊。

基礎語法

1. ( 引數 ) -> 方法體
2. ( 引數 ) -> { 方法體; };

重要特徵

  • 可選型別宣告: 不需要申明引數型別,編譯器統一識別引數值
a -> a + 1; 
  • 可選的引數圓括號: 一個引數可以省略圓括號,但多個引數不能省略圓括號
a -> a + 1; //一個引數
(int a,int b) -> a - b; //多個引數
//根據可選型別宣告,多個引數可以省略為
(a,b) -> a + b;
  • 可選的大括號: 如果方法體只有一個語句,可以省略大括號
a -> a+1;  
  • 可選的返回關鍵字: 如果主體只有一個表示式返回值則編譯器會自動返回值,大括號需要指定明表示式返回了一個數值。
//接收一個String,直接在控制檯輸出,無返回值
(String s) -> System.out.print(s);
// 接收一個String,返回String
(String s) -> { return s; }

程式碼範例

package test;

public  class Test{
	public static void main(String args[]){
		Test tester = new Test();
		/**
		 *  定義具體計算
		 */
	      // 型別宣告
	      MathOperation addition = (int a, int b) -> a + b;
	        
	      // 不用型別宣告
	      MathOperation subtraction = (a, b) -> a - b;
	        
	      // 大括號中的返回語句
	      MathOperation multiplication = (int a, int b) -> { return a * b; };
	        
	      // 沒有大括號及返回語句
	      MathOperation division = (int a, int b) -> a / b;
	        
	      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);
	      greetService1.sayMessage("Runoob");
	        
	      // 用括號
	      GreetingService greetService2 = (message) ->
	      System.out.println("Hello " + message);
	      greetService2.sayMessage("Google");
	   }
	    
	   //數位計算
	   interface MathOperation {
	      int operation(int a, int b);
	   }
	   //接收數位,具體進行什麼計算
	   private int operate(int a, int b, MathOperation mathOperation){
	      return mathOperation.operation(a, b);
	   }
	    
	   
	   interface GreetingService {
	      void sayMessage(String message);
	   }
	   
}

輸出結果為:

10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google

注意

  • Lambda 表達是主要是用來定義行內執行的方法型別介面,例如,一個簡單方法介面。
  • Lambda 表示式免去了使用匿名方法的麻煩。

變數作用域

Lambda 表達是隻能應用 final 的局外變數,也就是不能再 lambda 內部修改定義在域外的區域性變數,否則編譯出錯。
程式碼範例:

package csdnTest;

public class LambdaTest2 {
	final static int number_1=3;
	final static int number_2=2;
	
	public static void main(String[] args) {
		Num num = (a,b) -> a+b;
		
		System.out.println(num.addNum(number_1, number_2));
		//結果為5
	}
	
	interface Num{
		int addNum(int a,int b); 
	}
}

我們也可以在 lambda 表示式中存取外層變數

package csdnTest;

public class LambdaTest2 {
//	final static int number_1=3;
//	final static int number_2=2;
	
	public static void main(String[] args) {
		
		final int number_1=2;
		final int number_2=3;
		
		Num num = (a,b) -> a+b;
		
		System.out.println(num.addNum(number_1, number_2));
		//結果為5
	}
	
	interface Num{
		int addNum(int a,int b); 
	}
}

lambda 表示式的變數可以不用 final ,但是必須不可被後邊的程式碼修改

package csdnTest;

public class LambdaTest2 {
	public static void main(String[] args) {
		
		int number_1=2;
		
		Num num = a ->number_1 = 5;//這裡報錯:Local variable number_1 defined in an enclosing scope must be final or effectively final
	
		System.out.println(num.addNum(number_1));
	}
	
	interface Num{
		int addNum(int a); 
	}
}

在 Lambda 表示式中不允許宣告一個和變數同名的引數

package csdnTest;

public class LambdaTest2 {
	public static void main(String[] args) {
		
		int a=2;
		
		Num num = a ->a;//報錯:Lambda expression's parameter a cannot redeclare another local variable defined in an enclosing scope. 
		
		System.out.println(num.addNum(a));
	}
	
	interface Num{
		int addNum(int a); 
	}
}

範例 forEach 遍歷集合

範例對像

package csdnTest;

public class LambdaPerson {	
	private String name;
	private String sex;
	private int age;
}

forEach 遍歷

package csdnTest;

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

public class LambdaTest2{
	public static void main(String[] args) {
		List<LambdaPerson> list = getPersonList();
        list.forEach(LambdaPerson -> System.out.println(LambdaPerson.toString()));
	}
	private static List<LambdaPerson> getPersonList(){
		LambdaPerson p1 = new LambdaPerson("張三","男",22);
		LambdaPerson p2 = new LambdaPerson("李四","男",21);
		LambdaPerson p3 = new LambdaPerson("趙麗","女",21);
		LambdaPerson p4 = new LambdaPerson("王五","男",21);
        List<LambdaPerson> list = new ArrayList<LambdaPerson>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);
        return list;
    }
}
//結果為
LambdaPerson [name=張三, sex=男, age=22]
LambdaPerson [name=李四, sex=男, age=21]
LambdaPerson [name=趙麗, sex=女, age=21]
LambdaPerson [name=王五, sex=男, age=21]

使用Lambda表示式代替匿名內部類

	//匿名內部類
	public void runable() {
		new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名內部類進入執行緒");
            }
        }).start();
	}
	//Lambda表示式
	public void runable() {
		 new Thread(() -> System.out.println("lambda進入執行緒")).start();
	}