作者:Sevenvidia
https://www.zhihu.com/question/20125256/answer/324121308
1、什么是Lambda?
我們知道,對于一個Java變數,我們可以賦給其一個“值”,

如果你想把“一塊代碼”賦給一個Java變數,應該怎么做呢?
比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變數:


在Java 8之前,這個是做不到的,但是Java 8問世之后,利用Lambda特性,就可以做到了,推薦:JDK8新特性之Lambda運算式,


當然,這個并不是一個很簡潔的寫法,所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的宣告,


這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變數,而“這塊代碼”,或者說“這個被賦給一個變數的函式”,就是一個Lambda運算式,
但是這里仍然有一個問題,就是變數aBlockOfCode的型別應該是什么?
在Java 8里面,所有的Lambda的型別都是一個介面,而Lambda運算式本身,也就是”那段代碼“,需要是這個介面的實作,這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda運算式本身就是一個介面的實作,直接這樣說可能還是有點讓人困擾,我們繼續看看例子,我們給上面的aBlockOfCode加上一個型別:


這種只有一個介面函式需要被實作的介面型別,我們叫它”函式式介面“,為了避免后來的人在這個介面中增加介面函式導致其有多個介面函式需要被實作,變成"非函式介面”,我們可以在這個上面加上一個宣告@FunctionalInterface, 這樣別人就無法在里面添加新的介面函式了:


這樣,我們就得到了一個完整的Lambda運算式宣告:



2、Lambda運算式有什么作用?
最直觀的作用就是使得代碼變得例外簡潔,
我們可以對比一下Lambda運算式和傳統的Java對同一個介面的實作:

這兩種寫法本質上是等價的,但是顯然,Java 8中的寫法更加優雅簡潔,并且,由于Lambda可以直接賦值給一個變數,我們就可以直接把Lambda作為引數傳給函式, 而傳統的Java必須有明確的介面實作的定義,初始化才行:


有些情況下,這個介面實作只需要用到一次,傳統的Java 7必須要求你定義一個“污染環境”的介面實作MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得干凈很多,

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!
直接上例子,
假設Person的定義和List


現在需要你列印出guiltyPersons List里面所有LastName以"Z"開頭的人的FirstName,
原生態Lambda寫法:定義兩個函式式介面,定義一個靜態函式,呼叫靜態函式并給引數賦值Lambda運算式,


這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔么?
當然可以,在Java 8中有一個函式式介面的包,里面定義了大量可能用到的函式式介面(java.util.function (Java Platform SE 8 )),
所以,我們在這里壓根都不需要定義NameChecker和Executor這兩個函式式介面,直接用Java 8函式式介面包里的Predicate


第一步簡化 - 利用函式式介面包:


靜態函式里面的for each回圈其實是非常礙眼的,這里可以利用Iterable自帶的forEach()來替代,forEach()本身可以接受一個Consumer
第二步簡化 - 用Iterable.forEach()取代foreach loop:


由于靜態函式其實只是對List進行了一通操作,這里我們可以甩掉靜態函式,直接使用stream()特性來完成,stream()的幾個方法都是接受Predicate
第三步簡化 - 利用stream()替代靜態函式:


對比最開始的Lambda寫法,這里已經非常非常簡潔了,但是如果,我們要求變一下,變成print這個人的全部資訊,及p -> System.out.println(p); 那么還可以利用Method reference來繼續簡化,所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression,格式如下:


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda運算式:


這基本上就是能寫的最簡潔的版本了,

Lambda配合Optional
這里假設我們有一個person object,以及一個person object的Optional wrapper:

Optional


只有當Optional
我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional
情況一 - 存在則開干


情況二 - 存在則回傳,無則回傳屁


情況三 - 存在則回傳,無則由函式產生


情況四 - 奪命連環null檢查


由上述四種情況可以清楚地看到,Optional

關于Java的Lambda, 還有東西需要討論和學習,比如如何handle lambda exception,如何利用Lambda的特性來進行parallel processing等,
總之,我只是一如既往地介紹個大概,讓你大概知道,哦!原來是這樣子就OK了,網上關于Lambda有很多相關的教程,多看多練,假以時日,必定有所精益,
推薦去我的博客閱讀更多:
1.Java JVM、集合、多執行緒、新特性系列教程
2.Spring MVC、Spring Boot、Spring Cloud 系列教程
3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程
4.Java、后端、架構、阿里巴巴等大廠最新面試題
覺得不錯,別忘了點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/88055.html
標籤:Java
上一篇:nginx配置websocket
