Lambda表達式

Lambda表達式

JDK1.8的新特性之一

函數式編程思想

在數學中,函數就是有輸入量、輸出量的一套計算方案,也就是“拿什麼東西做什麼事情”。相對而言,面向對象過分強調“必須通過對象的形式來做事情”,而函數式思想則儘量忽略面向對象的複雜語法——強調做什麼,而不是以什麼形式做。
我們真的希望創建一個匿名內部類對象嗎?不。我們只是爲了做這件事情而不得不創建一個對象。我們真正希望做的事情是:將 run 方法體內的代碼傳遞給 Thread 類知曉。
傳遞一段代碼——這纔是我們真正的目的。而創建對象只是受限於面向對象語法而不得不採取的一種手段方式。
那,有沒有更加簡單的辦法?如果我們將關注點從“怎麼做”迴歸到“做什麼”的本質上,就會發現只要能夠更好地達到目的,過程與形式其實並不重要

Lambda引入

首先我們先看一個傳統的匿名內部類方式創建線程

public class ThreadDemo {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我是一個線程!");
            }
        }).start();
    }
}

對於 Runnable 的匿名內部類用法,可以分析出幾點內容
1.Thread 類需要 Runnable 接口作爲參數,其中的抽象 run 方法是用來指定線程任務內容的核心;
2.爲了指定 run 的方法體,不得不需要 Runnable 接口的實現類;
3.爲了省去定義一個 RunnableImpl 實現類的麻煩,不得不使用匿名內部類;
4.必須覆蓋重寫抽象 run 方法,所以方法名稱、方法參數、方法返回值不得不再寫一遍,且不能寫錯;
5.而實際上,似乎只有方法體纔是關鍵所在。

Lambda表達式格式:
Lambda省去面向對象的條條框框,格式由3個部分組成:
一些參數
一個箭頭
一段代碼
Lambda表達式的標準格式爲:(參數類型 參數名稱) -> { 代碼語句 }

格式說明:
小括號內的語法與傳統方法參數列表一致:無參數則留空;多個參數則用逗號分隔。
-> 是新引入的語法格式,代表指向動作。
大括號內的語法與傳統方法體要求基本一致。

Lambda表達式寫法:

public class ThreadDemo {
    public static void main(String[] args) {
        //匿名內部類創建線程方式
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我是一個線程!");
            }
        }).start();
        
 		System.out.println("=============Lambda表達式=============");
        
        //Lambda表達式方式
        new Thread(()-> {
                System.out.println("我是一個線程!");
        }).start();
    }
}

可以看到簡化了較多的代碼 ,其實根據Lambda表達式的簡化規則,我們還可以對代碼進行更深層次的簡化。

public class ThreadDemo {
    public static void main(String[] args) {
        //匿名內部類創建線程方式
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我是一個線程!");
            }
        }).start();

        System.out.println("=============Lambda表達式=============");

        //Lambda表達式方式
        new Thread(()-> {
                System.out.println("我是一個線程!");
        }).start();

        System.out.println("=============Lambda表達式最終簡化=============");

        //Lambda表達式進一步簡化
        new Thread(()-> System.out.println("我是一個線程!")).start();
    }
}

結果:
我是一個線程!
=============Lambda表達式=============
我是一個線程!
=============Lambda表達式最終簡化=============
我是一個線程!

我們可以看到最終的結果是一致的,證明我們使用的Lambda表達式是正確的。

Lambda表達式使用前提

  • 使用Lambda必須要有接口作爲參數傳遞,並且要求接口中有且僅有一個抽象方法。

Lambda表達式簡化規則

  • 參數類型可以省略。
  • 如果參數僅有一個,小括號可以省略
  • 如果方法體只有一條語句,大括號及分號也可以省略,如果有return的話也需要省略

最後我們演示一下有參數並且有返回值的寫法。

//創建一個Person類
public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Integer getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

//測試類
public class Demo {
    public static void main(String[] args) {

		ArrayList<Person> list = new ArrayList<Person>();
        list.add(new Person("張三",20));
        list.add(new Person("李四",18));
        list.add(new Person("王五",25));

		//原始方式,對數組進行排序
        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o2.getAge() - o1.getAge();
            }
        });

 		System.out.println("=============Lambda表達式=============");
 
		//Lambda方式
        Collections.sort(list, (o1, o2)-> {
                return o2.getAge() - o1.getAge();
        });

	 	System.out.println("=============Lambda表達式最終簡化=============");
	 	
		//Lambda方式最終版,當參數只有一個的時候小括號也可以不寫
        Collections.sort(list,(o1, o2) -> o2.getAge() - o1.getAge());
     }
}


結果:
[Person{name='王五', age=25}, Person{name='張三', age=20}, Person{name='李四', age=18}]

當一個接口中只有一個抽象方法,並且作爲方法參數時也可以使用Lambda表達式簡化
這種情況下也可以使用Lambda表達式:

//只有一個抽象方法的接口
public interface Work {
    void work();
}


//測試類
public class Test {
    public static void main(String[] args) {
        //原始
        method(new Work() {
            @Override
            public void work() {
                System.out.println("我喜歡工作!");
            }
        });

        //Lambda
        method(()->{
                System.out.println("我喜歡工作!");
        });

        //Lambda最簡化
        method(()-> System.out.println("我喜歡工作!"));
    }

	//該方法的參數是接口,該接口中就一個抽象方法
    private static void method(Work work){
        work.work();
    }
}

下一篇是Stream流,這個流跟IO流完全不一樣,它也是JDK1.8以後的新特性之一。

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