文章出處

廉頗老矣,尚能飯否

Java,這位已經20多歲的編程語言,稱得上是編程語言界的老大哥了。他曾經攻城略地,碾壓各路編程語言小弟,風光無限,不可一世。現在,也是家大業大,江湖地位,很難撼動。
但是,這依然無法阻擋人們對其未來發展趨勢的懷疑。這么多年過去了,江湖上新出來的各路小弟,悉數拿出自己的看家本領,確實讓老大哥有些坐不住了,業界都在擔心“廉頗老矣,尚能飯否”。
可以肯定的一點是,如果Java僅靠吃老本來維持自己的江湖地位是非常危險的。但是,他沒有這么做!今天要說的Lambda就是一個鐵證。

早在2014年,Oracle就發布了Java8,帶來了讓人振奮的不少新特性:

  • Lambda表達式
  • 接口的默認方法與靜態方法
  • 方法引用
  • 重復注解
  • 擴展注解的支持
  • Optional
  • Stream
  • Date/Time API
  • JavaScript引擎Nashorn
  • Base64

周邊Java的程序員很多,Java8的不多,為什么

但是從我周邊來看,大家都多多少少聽說過其中的一些新特性,但是切切實實把這些特性和API用起來的不多。當然,這其中原因很多。
有些因為歷史原因,很難在架構上動手腳,從Java6換到Java8只是一句話的事,但是要實行起來,可能會帶來讓人夜不能眠的各種雷,所以很多人在老實的框架下待著,用著上古的Java6。
有些靈活性比較強的項目,通過一次大升級,轉到了Java8陣營,但是各位碼農覺得Java6或者Java7都完全夠用,即便不夠用或者不好用,想想又要花時間研究這些新特性,還是就這么將就著寫吧。
有些業界從業者,早已經用上這些新特性了,只是他們不在Java陣營。比如14年,我身邊就有人開始用Scala在Spark下完成大數據計算的業務和數據處理了,時常能聽到他們說,Scala真的是太好用了。同時,伴隨著大前端的火熱,駐扎在JS陣營的也是不在少數,JS靈活的語法也是讓人欲罷不能。這些語言早早的具備了Java8中的面向函數編程的思想。

Lambda

public class ThreadWithoutLambda {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("This is runable thread");
            }
        });

        thread.start();
    }
}

這樣的程序,是不是再熟悉不過了。仔細瞧瞧這段代表要表達的意思其實就是啟動一個線程,這個線程只做了一件事——打印“This is runnable thread”。有沒有那么一瞬間看這個run方法有點不順眼,如果有請看下面的寫法

public class ThreadWithLambda {
    public static void main(String[] args) {
        Thread lambdaThread = new Thread(() -> System.out.println("This is lambda runnable thread"));
        lambdaThread.start();
    }
}

如何你用的是Java8的jdk,那么運行這兩個類會發現,效果完全一樣,而這,就是你聽過很久的Lambda表達式的寫法。如果你覺得有點意思,繼續往下看。

我們把上面Lambda寫法的語句拿出來

new Thread(() -> System.out.println("This is lambda runnable thread"))

在new Thread的構造方法里,我們看到傳遞的值不是我們經常看到的一個變量或者一個對象。憑著感覺和對于Thread的了解,這應該是一個函數,在Java8之前,我們能想到這種傳遞方式應該就是匿名內部類了,從某種程度上來說,Lambda就充當了匿名內部類這樣的角色,但是實現起來,比其更加簡潔易讀。

除了Runnable接口的run方法,我們還有再熟悉不過的用于集合元素比較器的Comparator類,Java8之前,我們想對于一個集合采用自定義的方式排序,可以這樣實現

public class ComparatorWithoutLambda {

    public static void main(String[] args) {
        List<Apple> apples = Arrays.asList(new Apple(100, "green"),
                                           new Apple(150, "red"),
                                           new Apple(120, "yellow"));

        System.out.println(apples);

        Collections.sort(apples, new Comparator<Apple>() {
            @Override
            public int compare(Apple o1, Apple o2) {
                return o1.getWeight().compareTo(o2.getWeight());
            }
        });

        System.out.println(apples);
    }
}

這里通過比較集合中的元素apple的weight屬性,按照weight的從小到大完成自定義排序。程序執行的結果如下

[Apple{weight=100, color='green'}, Apple{weight=150, color='red'}, Apple{weight=120, color='yellow'}]
[Apple{weight=100, color='green'}, Apple{weight=120, color='yellow'}, Apple{weight=150, color='red'}]

附上Apple類的實現

public class Apple {
    private Integer weight;
    private String color;

    public Apple() {
    }

    public Apple(int weight, String color) {
        this.weight = weight;
        this.color = color;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "weight=" + weight +
                ", color='" + color + '\'' +
                '}';
    }
}

使用Lambda的方式實現,同樣很簡潔,很驚艷

public class ComparatorWithLambda {

    public static void main(String[] args) {
        List<Apple> apples = Arrays.asList(new Apple(100, "green"),
                                           new Apple(150, "red"),
                                           new Apple(120, "yellow"));

        System.out.println(apples);
        Collections.sort(apples, (Apple apple1, Apple apple2) -> apple1.getWeight().compareTo(apple2.getWeight()));
        System.out.println(apples);
    }
}

Lambda語法

下面通過上面的例子看看Lambda的構成

Lambda表達式可以理解為可傳遞匿名函數的一種方式。沒有名稱,有參數、函數體和返回類型。

  • 匿名——他確實沒有像普通函數那樣有自己的名字,先前的匿名函數也是如此
  • 參數——上面的a1和a2就是參數,可以對應到沒用Lambda時函數參數的聲明
  • 函數體——就是上面的“apple1.getWeight().compareTo(apple2.getWeight())”,相當于沒有Lambda中的compare函數的函數體
  • 返回類型——從函數體,我們可以推斷(專業來說叫做類型推斷)函數體返回的是一個boolean類型。
  • 箭頭——將參數與函數體隔開

Lambda的語法主要有兩種形式
(parameters) -> expression
(paramters) -> {statemenst;}
可要仔細看好這兩種表達式語法,像(String s) -> return "hello world," + s;這種可不能成為Lambda表達式。

Lambda寫法的應用舉例

(List list) -> list.isEmpty(); ​布爾表達式
() -> new Apple(10); 創建一個對象
(Apple a) -> {System.out.println("a.getColor");} 消費一個對象
(Stirng s) -> s.length(); 從對象中選擇、抽取
(int a, int b) -> a+b; ​ 組合兩個值

今天先到這吧~~~
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注JackieZheng的微信公眾號,我會將我的文章推送給您,并和您一起分享我日常閱讀過的優質文章。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()