Java 8 新特性(一)lambda表達式



Java 9 好像也快出了,不過我連Java 8的新特性都還沒認真研究過,所以這幾篇文章就是來介紹Java 8的新特性的。首先,第一個重要的特性就是傳說中的lambda表達式了,雖然初學可能覺得這東西很難理解,但是一旦學會了,你就會發現離不開它了。

在現代編程語言中,lambda表達式這個語言特性已經成爲了標配。當然不同語言中的lambda表達式概念和實現形式可能會稍有差別。不過不管在哪種語言中,我們都可以把lambda表達式簡單的理解爲匿名函數。在Java中,lambda表達式和只有一個方法的接口是差不多的,所以這樣的接口又叫做SAM接口(Single Abstract Method interfaces)。

初識lambda表達式

說了半天,下面先來看看實際例子吧。我們在編寫多線程代碼的時候,常常需要編寫實現 Runnable 的類。有時候爲了省事,我們會寫成匿名內部類的形式。

Runnable task1 = new Runnable() { @Overridepublic void run() {System.out.println("任務一");}};

匿名內部類不好理解,而且寫起來也非常醜陋。由於 Runnable 接口內只有一個方法,所以它是一個SAM接口,我們可以用lambda表達式改寫它。那麼改寫之後是什麼樣子的呢?不要驚訝,只需要一行代碼。

Runnable task2 = () -> System.out.println("任務二");

因此,我們可以看到lambda表達式的簡潔之處。下面就來詳細介紹一下lambda表達式的形式。

lambda表達式形式

lambda表達式可以用在需要SAM接口對象的地方,由於編譯器這時候知道所需要的接口和對應方法的簽名。所以lambda表達式的類型聲明可以省略,具體類型由編譯器自行推斷。lambda表達式的基本形式如下。

(參數列表) -> {方法體}

爲了方便說明,我這裏定義了一組接口,用於之後的lambda表達式實現。

@FunctionalInterfaceinterface Interface1 { void f();}@FunctionalInterfaceinterface Interface2 { void f(int a);}@FunctionalInterfaceinterface Interface3 { void f(int a, int b);}@FunctionalInterfaceinterface Interface4 { int f(int a, int b);}

無參lambda

先來看看無參數的lambda表達式。特別地,如果方法體只有一行代碼,可以省略方法體的大括號。

Interface1 interface1 = new Interface1() {@Overridepublic void f() {System.out.println("f");}};Interface1 lambda1 = () -> {System.out.println("f");};//如果方法體只有一行代碼,可以省略大括號Interface1 lambda1a = () -> System.out.println("f");

多個參數的lambda

我們可以看到由於編譯器可以進行類型推斷,所以lambda表達式的參數列表不需要參數類型聲明,而且由於我只有一行代碼,所以大括號也省略了。

//多個參數lambdaInterface3 interface3 = new Interface3() {@Override public void f(int a, int b) {System.out.println(a + b);}};Interface3 lambda3 = (a, b) -> System.out.println(a + b);

帶返回值的lambda

帶返回值的lambda表達式其實和普通的一樣,只不過需要在方法體的最後使用 return 語句。值得注意的是最後一個例子,如果方法體本身足夠簡單,可以直接將返回值表達式寫在lambda表達式的右邊,編譯器也會正確對待這種情況。

//帶有返回值的lambdaInterface4 interface4 = new Interface4() { @Overridepublic int f(int a, int b) { return a + b;}};Interface4 lambda4 = (a, b) -> { return a + b;};Interface4 lambda4a = (a, b) -> a + b;

Java大牛學習交流:689024304

單個參數的lambda

如果lambda表達式只有一個參數,那麼參數列表的小括號也可以省略,例如下面的第二個例子。下面第三個例子演示了另一個新語法 方法引用 ,如果lambda表達式的形式是 單個參數a -> 某個只有一個參數的方法(a) ,那麼就可以簡寫成方法引用的形式 類::方法 。方法引用是一個新語法,如果見到了不要奇怪,這也是正確的Java代碼。

//一個參數的lambdaInterface2 interface2 = new Interface2() {@Override public void f(int a) {System.out.println(a);}};Interface2 lambda2 = (a) -> System.out.println(a);Interface2 lambda2a = a -> System.out.println(a);Interface2 methodReference = System.out::println;

函數接口

@FunctionalInterface 註解

如果查看JDK源碼的一些接口,會發現它們上面添加了 @FunctionalInterface 註解。例如上面提到的 Runnable 接口。

@FunctionalInterfacepublic interface Runnable { public abstract void run();}

這個註解用於標註函數接口,也就是上面提到的SAM接口。如果一個接口中包含了不止一個方法,那麼函數接口註解就會觸發編譯錯誤。這個功能類似於 @Override 註解。當然並不是說要使用lambda表達式必須標記這個註解,只要接口中只有一個方法,那麼就可以使用lambda表達式。

其實函數接口可以包括不止一個方法,除了一個普通的抽象方法之外,函數接口還可以包含一個在 java.lang.Object 類中聲明的方法。Java 8新增了默認方法特性,如果接口的實現類沒有實現 java.lang.Object 類中的這些基本方法,那麼就會調用 java.lang.Object 類中的實現作爲默認實現。

@FunctionalInterfaceinterface Interface5 { void f(); String toString();}

預定義的函數接口

java.util.function 包下定義了大量預定義的函數接口,它們包含了各種各樣的形式,基本涵蓋了編程的各個方面。同學們最好對這些函數接口的形式稍作了解,以後碰到的時候就不會一頭霧水了。

Java 8 新特性(一)lambda表達式

函數接口

lambda表達式應用

編寫線程

前面提到了,可以使用lambda表達式簡化線程代碼的編寫,不再需要冗長的匿名內部類。

//編寫線程Runnable task = () -> System.out.println("簡單的任務");Executor executor = Executors.newCachedThreadPool();executor.execute(task);

編寫比較器

比方說我們有一個學生類,有姓名和年齡兩個字段。如果需要按照某種規則來進行排序,可以使用比較器 Comparator 接口來比較,利用lambda表達式同樣可以簡化這部分代碼的編寫。

class Student { private String name; private int age; //其餘方法已省略}

可以看到比較規則只需要一條lambda表達式即可傳入,非常方便。後面兩個例子是 Comparator 接口新增的工具方法,可以幫助我們簡化比較代碼的編寫,這裏使用了方法引用來簡化代碼。comparing 等方法的返回值仍然是 Comparator ,所以可以鏈式調用進行多級比較。

List<Student> students = new ArrayList<>();students.add(new Student("yitian", 25));students.add(new Student("anna", 26));students.add(new Student("wang5", 24));students.sort((a, b) -> a.getAge() - b.getAge());System.out.println(students);students.sort(Comparator.comparing(Student::getName));System.out.println(students);students.sort( Comparator.comparing(Student::getName) .thenComparing(Student::getAge));System.out.println(students);

轉:http://www.tuicool.com/articles/Jb2M7jf


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