【Java8新特性】Lambda表達式基礎語法,都在這兒了!!

寫在前面

前面積極響應讀者的需求,寫了兩篇Java新特性的文章。有小夥伴留言說:感覺Lambda表達式很強大啊!一行代碼就能夠搞定那麼多功能!我想學習下Lambda表達式的語法,可以嗎?我的回答是:沒問題!這不,Lambda表達式來了!

匿名類到Lambda表達式

我們先來看看從匿名類如何轉換到Lambda表達式呢?

這裏,我們可以使用兩個示例來說明如何從匿名內部類轉換爲Lambda表達式。

  • 匿名內部類到Lambda表達式

使用匿名內部類如下所示。

Runnable r = new Runnable(){
    @Override
    public void run(){
        System.out.println("Hello Lambda");
    }
}

轉化爲Lambda表達式如下所示。

Runnable r = () -> System.out.println("Hello Lambda");
  • 匿名內部類作爲參數傳遞到Lambda表達式作爲參數傳遞

使用匿名內部類作爲參數如下所示。

TreeSet<Integer> ts = new TreeSet<>(new Comparator<Integer>(){
    @Override
    public int compare(Integer o1, Integer o2){
        return Integer.compare(o1, o2);
    }
});

使用Lambda表達式作爲參數如下所示。

TreeSet<Integer> ts = new TreeSet<>(
	(o1, o2) -> Integer.compare(o1, o2);
);

從直觀上看,Lambda表達式要比常規的語法簡潔的多。

Lambda表達式的語法

Lambda表達式在Java語言中引入了 “->” 操作符, “->” 操作符被稱爲Lambda表達式的操作符或者箭頭操作符,它將Lambda表達式分爲兩部分:

  • 左側部分指定了Lambda表達式需要的所有參數。

Lambda表達式本質上是對接口的實現,Lambda表達式的參數列表本質上對應着接口中方法的參數列表。

  • 右側部分指定了Lambda體,即Lambda表達式要執行的功能。

Lambda體本質上就是接口方法具體實現的功能。

我們可以將Lambda表達式的語法總結如下。

1.語法格式一:無參,無返回值,Lambda體只有一條語句

Runnable r = () -> System.out.println("Hello Lambda");

具體示例如下所示。

@Test
public void test1(){
    Runnable r = () -> System.out.println("Hello Lambda");
    new Thread(r).start();
}

2.語法格式二:Lambda表達式需要一個參數,並且無返回值

Consumer<String> func = (s) -> System.out.println(s);

具體示例如下所示。

@Test
public void test2(){
    Consumer<String> consumer = (x) -> System.out.println(x);
    consumer.accept("Hello Lambda");
}

3.語法格式三:Lambda只需要一個參數時,參數的小括號可以省略

Consumer<String> func = s -> System.out.println(s);

具體示例如下所示。

@Test
public void test3(){
    Consumer<String> consumer = x -> System.out.println(x);
    consumer.accept("Hello Lambda");
}

4.語法格式四:Lambda需要兩個參數,並且有返回值

BinaryOperator<Integer> bo = (a, b) -> {
    System.out.println("函數式接口");
    return a + b;
};

具體示例如下所示。

@Test
public void test4(){
    Comparator<Integer> comparator = (x, y) -> {
        System.out.println("函數式接口");
        return Integer.compare(x, y);
    };
}

5.語法格式五:當Lambda體只有一條語句時,return和大括號可以省略

BinaryOperator<Integer> bo = (a, b) -> a + b;

具體示例如下所示。

@Test
public void test5(){
    Comparator<Integer> comparator = (x, y) ->  Integer.compare(x, y);
}

6.語法格式六:Lambda表達式的參數列表的數據類型可以省略不寫,因爲JVM編譯器能夠通過上下文推斷出數據類型,這就是“類型推斷”

BinaryOperator<Integer> bo = (Integer a, Integer b) -> {
    return a + b;
};

等同於

BinaryOperator<Integer> bo = (a, b) -> {
    return a + b;
};

上述 Lambda 表達式中的參數類型都是由編譯器推斷得出的。 Lambda 表達式中無需指定類型,程序依然可以編譯,這是因爲 javac 根據程序的上下文,在後臺推斷出了參數的類型。 Lambda 表達式的類型依賴於上下文環境,是由編譯器推斷出來的。這就是所謂的“類型推斷”。

函數式接口

Lambda表達式需要函數式接口的支持,所以,我們有必要來說說什麼是函數式接口。

只包含一個抽象方法的接口,稱爲函數式接口。

可以通過 Lambda 表達式來創建該接口的對象。(若 Lambda表達式拋出一個受檢異常,那麼該異常需要在目標接口的抽象方法上進行聲明)。

可以在任意函數式接口上使用 @FunctionalInterface 註解,這樣做可以檢查它是否是一個函數式接口,同時 javadoc 也會包含一條聲明,說明這個接口是一個函數式接口。

我們可以自定義函數式接口,並使用Lambda表達式來實現相應的功能。

例如,使用函數式接口和Lambda表達式實現對字符串的處理功能。

首先,我們定義一個函數式接口MyFunc,如下所示。

@FunctionalInterface
public interface MyFunc <T> {
    public T getValue(T t);
}

接下來,我們定義一個操作字符串的方法,其中參數爲MyFunc接口實例和需要轉換的字符串。

public String handlerString(MyFunc<String> myFunc, String str){
    return myFunc.getValue(str);
}

接下來,我們對自定義的函數式接口進行測試,此時我們傳遞的函數式接口的參數爲Lambda表達式,並且將字符串轉化爲大寫。

@Test
public void test6(){
    String str = handlerString((s) -> s.toUpperCase(), "binghe");
    System.out.println(str);
}

運行test6方法,得出的結果信息如下所示。

BINGHE

我們也可以截取字符串的某一部分,如下所示。

@Test
public void test7(){
    String str = handlerString((s) -> s.substring(0,4), "binghe");
    System.out.println(str);
}

運行test7方法,得出的結果信息如下所示。

bing

可以看到,我們可以通過handlerString(MyFunc<String> myFunc, String str)方法結合Lambda表達式對字符串進行任意操作。

注意:作爲參數傳遞 Lambda 表達式:爲了將 Lambda 表達式作爲參數傳遞,接收Lambda 表達式的參數類型必須是與該 Lambda 表達式兼容的函數式接口的類型 。

寫在最後

如果覺得文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公衆號,跟冰河學習Java8新特性。

最後,附上Java8新特性核心知識圖,祝大家在學習Java8新特性時少走彎路。

在這裏插入圖片描述

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