入門lambda表達式(一)

引文

  在這篇文章中,我想介紹一下Java 8最吸引人的新特性——lambda表達式。
  先貼上lambda表達式的基本語法,有兩種形式:java

  • (parameters) -> expression
  • (parameters) -> {expressions}

  lambda容許把函數做爲一個方法的參數傳遞進方法中,體現了函數式編程思想。使用lambda表達式可使代碼變得更加簡潔緊湊。lambda表達式的本質只是一個所謂的「語法糖」,並無爲Java語言添加新的功能,而是對已有功能進行了封裝,由編譯器推斷並轉換爲常規的代碼,所以能夠用更少的代碼來實現一樣的功能。我我的以爲,lambda表達式雖好,但不要亂用,用在合適的地方,能夠有效減小代碼量,使代碼更加簡潔,而濫用只會下降代碼的可讀性,使程序難以調試和維護。那麼lambda表達式的應用場景是什麼呢?
  網上有不少lambda表達式的例子,我看了半天,以爲無外乎就兩個場景(我的淺顯觀點......):
  一是代替函數式接口。函數式接口簡單來講就是隻包含一個抽象方法的接口,好比Java標準庫中的java.lang.Runnable和java.util.Comparator都是典型的函數式接口。對於函數式接口,除了可使用Java中標準的方法來建立實現對象以外,還可使用lambda表達式來建立實現對象,這能夠在很大程度上簡化代碼的實現。在使用lambda表達式時,只須要提供形式參數和方法體。因爲函數式接口只有一個抽象方法,因此經過lambda表達式聲明的方法體確定是這個惟一的抽象方法的實現,並且形式參數的類型能夠根據方法的類型聲明進行自動推斷(即形式參數能夠省略類型)。
  第二個場景,就是和集合配合使用。Java 8新增了兩個對集合數據進行批量操做的包:java.util.function和java.util.stream。能夠說,lambda表達式和stream是自Java語言添加泛型和註解以來最大的變化,lambda表達式很大程度上影響了咱們在處理集合時的編碼方式。express

Lambda表達式基本用法

  下面,我經過幾個典型的例子帶你們領略lambda表達式的強悍:編程

使用lambda表達式實現Runnable接口

傳統方式ide

public class runnableTest {

    public static void main(String[] args) {
        new Thread(new Runnable() {
            public void run() {
                System.out.println("I am Hawk.");
            }
        }).start();
    }
}
複製代碼

使用lambda表達式函數式編程

public class runnableTest {

    public static void main(String[] args) {
        new Thread(() ->
            System.out.println("I am Hawk.")
        ).start();
    }
}
複製代碼

  經過這個例子,咱們也能夠進一步熟悉lambda表達式的聲明方式:由形式參數和方法體兩部分組成,中間經過「->」分隔。形式參數一般狀況下不須要包含類型聲明,能夠進行自動推斷。由於 System.out.println("I am Hawk.") 是單行語句,能夠不用花括號「{}」括起來,若是方法體包含多行語句,則須要用「{}」括起來。函數

使用lambda表達式實現Comparator接口

  關於Comparator的機制,不在咱們此次的討論範圍內,我有時間...額...大概會寫。總之,當咱們相比較的對象沒有實現Comparable接口時,可使用Comparator接口並實現其中的compare方法進行比較。好比說,有這樣一個Penple類:編碼

// 使用lombok註解自動生成構造器與get、set方法等
@Data
@NoArgsConstructor
@AllArgsConstructor
public class People {
    
    private String name;
    
    private Integer age;
}
複製代碼

  如今我想按照年齡對People對象進行排序:
傳統方式spa

public class ComparatorTest {

    public static void main(String[] args) {
        List<People> peopleList = new ArrayList<>();
        peopleList.addAll(Arrays.asList(new People("a", 20), new People("b", 21), new People("c", 22)));
        Collections.sort(peopleList, new Comparator<People>() {
            @Override
            public int compare(People p1, People p2) {
                return p1.getAge().compareTo(p2.getAge());
            }
        });
    }
}
複製代碼

使用lambda表達式調試

// 方法一
public class ComparatorTest {

    public static void main(String[] args) {
        List<People> peopleList = new ArrayList<>();
        peopleList.addAll(Arrays.asList(new People("a", 20), new People("b", 21), new People("c", 22)));
        Collections.sort(peopleList, (p1, p2) ->
            p1.getAge().compareTo(p2.getAge()));
    }
}

// 方法二
public class ComparatorTest {

    public static void main(String[] args) {
        List<People> peopleList = new ArrayList<>();
        peopleList.addAll(Arrays.asList(new People("a", 20), new People("b", 21), new People("c", 22)));
        peopleList.sort(Comparator.comparing(People::getAge));
    }
}
複製代碼

  不知道你們咋想的,反正我當時知道還有方法二這種寫法時是真的驚了。感受Java 8中的集合類型在增長了lambda表達式的支持以後變得......emmm高深莫測。須要注意一點,在方法二中,還使用了Java 8的另外一個新特性——方法引用,就是那兩個冒號「::」(有點C++的趕腳)。方法引用能夠在不調用某個方法的狀況下引用一個方法,是另外一種實現函數式接口的方法,能夠進一步簡化代碼。code

使用lambda表達式對列表進行迭代

傳統方法

public class foreachTest {

    public static void main(String[] args) {
        List<String> stringList = new ArrayList<>();
        stringList.addAll(Arrays.asList("a", "b", "c"));
        for (String str : stringList) {
            System.out.println(str);
        }
    }
}
複製代碼

使用lambda表達式

public class foreachTest {

    public static void main(String[] args) {
        List<String> stringList = new ArrayList<>();
        stringList.addAll(Arrays.asList("a", "b", "c"));
        stringList.forEach(System.out::println);
    }
}
複製代碼

  額......先寫到這裏吧,由於stream部份內容較多,過幾天再補充完。此次主要介紹了使用lambda表達式的第一個場景——代替函數式接口。這是一個趨勢,但願你們在從此的編碼中,能逐漸拋棄匿名內部類,改用lambda這種更爲簡潔的寫法。下次我將重點介紹lambda在集合中的使用以及如何與stream進行配合。

相關文章
相關標籤/搜索