1. 程式人生 > >Java瘋狂講義筆記——Lambda表示式

Java瘋狂講義筆記——Lambda表示式

Java8新增的Lambda表示式

【特性】
支援將程式碼塊作為方法引數,Lambda表示式允許使用更簡潔的程式碼來建立只有一個抽象方法的介面(這種介面被稱為函式式介面)的例項。

【組成部分】
1,形參列表
形參列表允許省略形參型別。如果形參列表中只有一個引數,甚至連形參列表的圓括號都可以省略。
2,箭頭(->)
3,程式碼塊
如果程式碼塊只包含一條語句,Lambda表示式允許省略程式碼塊的花括號。
Lambda程式碼塊只有一條return語句,甚至可以省略return關鍵字。
Lambda表示式需要返回值,而它的程式碼塊中僅有一條省略了return語句,Lambda表示式會自動返回這條語句的值。

【Lambda表示式的型別】
被稱為“目標型別”(target type),Lambda表示式的目標型別必須是“函式式介面(functional interface)”。
Lambda表示式的結果被當成物件,即返回值是物件。

【函式式介面】
函式式介面代表只包含一個抽象方法的介面。
函式式介面可以包含多個預設方法、類方法,但只能宣告一個抽象方法。

【Lambda表示式的限制】
1,Lambda表示式的目標型別必須是明確的函式式介面。
2,Lambda表示式只能為函式式介面建立物件。Lambda表示式只能實現一個方法,因此它只能為只有一個抽象方法的介面(函式式介面)建立物件。

【Lambda表示式常見使用方式】
1,將Lambda表示式賦值給函式式介面型別的變數。
2,將Lambda表示式作為函式式介面型別的引數傳給某個方法。
3,使用函式式介面對Lambda表示式進行強制型別轉換。

【Lambda表示式的本質】
使用簡潔的語法來建立函式式介面的例項——這種語法避免了匿名內部類的煩瑣。

【方法引用與構造器引用】
1,引用類方法
  類名::類方法
    Converter converter1 = Integer::valueOf;
  (a,b...) -> 類名.類方法(a,b...)
    Converter converter1 = from -> Integer.valueOf(from);
2,引用特定物件的例項方法
  特定物件::例項方法
    Converter converter2 = "fkit.org"::indexOf;
  (a,b...) -> 特定物件.例項方法(a,b...)
    Converter converter2 = from -> "fkit.org".indexOf(from);
3,引用某類物件的例項方法
  類名::例項方法
    MyTest mt = String::substring;
  (a,b...) -> a.例項方法(b...)
    MyTest mt = (a,b,c) -> a.substring(b,c);
4,引用構造器
  類名::new
    YourTest yt = JFrame::new;
  (a,b...) -> new 類名(a,b...)
    YourTest yt = (String a) -> new JFrame(a);

【Lambda表示式與匿名內部類的聯絡和區別】
相同:
1,Lambda表示式與匿名內部類一樣,都可以直接訪問"effectively final"的區域性變數,以及外部類的成員變數(包括例項變數和類變數)。
2,Lambda表示式建立的物件與匿名內部類生成的物件一樣,都可以直接呼叫從介面中繼承的預設方法。
區別:
1,匿名內部類可以為任意介面建立例項——不管介面包含多少個抽象方法,只要匿名內部類實現所有的抽象方法即可;
     但Lambda表示式只能為函式式介面建立例項。
2,匿名內部類可以為抽象類甚至普通類建立例項;
     但Lambda表示式只能為函式式介面建立例項。
3,匿名內部類實現的抽象方法的方法體允許呼叫介面中定義的預設方法;
     但Lambda表示式的程式碼塊不允許呼叫介面中定義的預設方法。

 


【示例1】
class Demo
{
  //該方法呼叫需要Eaterble物件
  public void eat(Eatable e) {
    System.out.println(e);
    e.taste();
  }

  //呼叫該方法需要Flyable物件
  public void drive(Flyable f) {
    System.out.println("我正在駕駛:" + f);
    f.fly("【碧空如洗的晴日】");
  }

  //呼叫該方法需要Addable物件
  public void test(Addable add) {
    System.out.println("5與3的和為:" + add.add(5,3));
  }

  public static void main(String[] args) {
    Demo d = new Demo();

    d.eat(()->System.out.println("蘋果的味道不錯!"));

    d.drive(weather->
    {
      System.out.println("今天的天氣是:" + weather);
      System.out.println("直升機飛行平穩");
    });

    d.test((a,b)->a+b);

  }
}

interface Eatable
{
  void taste();
}

interface Flyable
{
  void fly(String weather);
}

interface Addable
{
  int add(int a, int b);
}

結果:
Demo$$Lambda$1/[email protected]
蘋果的味道不錯!
我正在駕駛:Demo$$Lambda$2/[email protected]
今天的天氣是:【碧空如洗的晴日】
直升機飛行平穩
5與3的和為:8


【示例2】
import java.util.Arrays;

class Demo
{
  public static void main(String[] args) {
    String[] arr1 = new String[]{"java","fkava","fkit","ios","android"};
    Arrays.parallelSort(arr1,(o1,o2) -> o1.length() - o2.length());
    System.out.println(Arrays.toString(arr1));
    int[] arr2 = new int[]{3,-4,25,16,30,18};
    Arrays.parallelPrefix(arr2, (left,right) -> left*right);
    System.out.println(Arrays.toString(arr2));
    long[] arr3 = new long[5];
    Arrays.parallelSetAll(arr3, operand -> operand*5);
    System.out.println(Arrays.toString(arr3));
  }
}


結果:
[ios, java, fkit, fkava, adnroid]
[3, -12, -300, -4800, -144000, -2592000]
[0, 5, 10, 15, 20]