Java8之Lambda表達(dá)式使用解讀
一、初識(shí)Lambda
Lambda 表達(dá)式(lambda expression)是一個(gè)匿名函數(shù),Lambda表達(dá)式基于數(shù)學(xué)中的λ演算得名,直接對(duì)應(yīng)于其中的lambda抽象(lambda abstraction),是一個(gè)匿名函數(shù),即沒有函數(shù)名的函數(shù)。
Lambda表達(dá)式可以表示閉包(注意和數(shù)學(xué)傳統(tǒng)意義上的不同)。
這是來自萬能的百度百科對(duì)于lambda表達(dá)式的解釋,懂的都懂,不懂的真是聽君一席話,如聽一席話。
Lambda表達(dá)式在Java8中及后續(xù)版本占據(jù)了舉足輕重的地位,對(duì)于函數(shù)式編程來說是必不可少的一環(huán),所以學(xué)會(huì)lambda表達(dá)式,對(duì)于使用Java8的同學(xué)是必經(jīng)之路
舉個(gè)栗子,Java8中的stream你們不會(huì)沒有用過吧?什么?你還在用Java7?阿巴阿巴阿巴…好吧,那我直接用代碼舉個(gè)栗子吧。
1.Lambda栗子
需求是這樣的,二哥第一次來到了大城市,到了大城市就去了 大 保 健,這個(gè)時(shí)候肯定就要選女朋友了,根據(jù)姓名、大小、價(jià)位等,咳咳咳…說錯(cuò)了,是根據(jù)姓名、鞋碼、身價(jià)來選擇,二哥要求經(jīng)理讓這些女朋友按照身價(jià)來正序排隊(duì)站好。
@Data @AllArgsConstructor public class Girl { private String name; private Double size; private Double price; }
public static void main(String[] args) { ArrayList<Girl> list = Lists.newArrayList(); list.add(new Girl("露西",33d,2000d)); list.add(new Girl("格蕾絲",36d,3000d)); list.add(new Girl("安娜",28d,1500d)); list.add(new Girl("克瑞斯",31d,1800d)); //匿名函數(shù)類實(shí)現(xiàn) list.sort(new Comparator<Girl>() { @Override public int compare(Girl o1, Girl o2) { return o1.getPrice().compareTo(o2.getPrice()); } }); list.stream().forEach(System.out::println); Collections.shuffle(list); System.out.println("-------------我是分隔符-----------------"); //lambda實(shí)現(xiàn) list.sort((Girl g1, Girl g2)-> g1.getPrice().compareTo(g2.getPrice())); list.stream().forEach(System.out::println); }
不難看出,兩種方式都實(shí)現(xiàn)了讓女朋友們按照身價(jià)排隊(duì)。那么我們著重來看看Lambda表達(dá)式。
2.Lambda表達(dá)式的組成
(Girl g1, Girl g2)-> g1.getPrice().compareTo(g2.getPrice());
- 參數(shù)列表:本例中是兩個(gè)Mask對(duì)象的參數(shù),采用的是Comparator接口中compare方法的參數(shù)。
- 箭頭:->把參數(shù)列表和主體分隔為兩個(gè)部分。
- 主體:本例中是把比較價(jià)格的表達(dá)式作為L(zhǎng)ambda表達(dá)式的返回。主體可以修改成另外一種寫法,含義是一樣的:
list.sort((Girl g1, Girl g2)-> { return g1.getPrice().compareTo(g2.getPrice()); });
由此可以看出,lambda表達(dá)式語法格式可以分為兩種:
- 1.(parameters) -> expression //參數(shù)列表加單條表達(dá)式
- 2.(parameters) ->{ statements; } //參數(shù)列表加花括號(hào)和多條語句
以下是lambda表達(dá)式的重要特征:
- 可選類型聲明:不需要聲明參數(shù)類型,編譯器可以統(tǒng)一識(shí)別參數(shù)值。
- 可選的參數(shù)圓括號(hào):一個(gè)參數(shù)無需定義圓括號(hào),但多個(gè)參數(shù)需要定義圓括號(hào)。
- 可選的大括號(hào):如果主體包含了一個(gè)語句,就不需要使用大括號(hào)。
- 可選的返回關(guān)鍵字:如果主體只有一個(gè)表達(dá)式返回值則編譯器會(huì)自動(dòng)返回值,大括號(hào)需要指定表達(dá)式返回了一個(gè)數(shù)值。
3.舉個(gè)栗子
// 1. 不需要參數(shù),返回值為 5 () -> 5 // 2. 接收一個(gè)參數(shù)(數(shù)字類型),返回其2倍的值 x -> 2 * x // 3. 接受2個(gè)參數(shù)(數(shù)字),并返回他們的差值 (x, y) -> x – y // 4. 接收2個(gè)int型整數(shù),返回他們的和 (int x, int y) -> x + y // 5. 接受一個(gè) string 對(duì)象,并在控制臺(tái)打印,不返回任何值(看起來像是返回void) (String s) -> System.out.print(s) // 6.接受兩個(gè)int參數(shù),多條語句進(jìn)行比較返回1或者0 (int s1, int s2)->{ if(s1>s2){ return 0; } return 1; }
二、Lambda更進(jìn)一步
1.類型推斷
//lambda實(shí)現(xiàn) list.sort((Girl g1, Girl g2)-> g1.getPrice().compareTo(g2.getPrice())); //lambda簡(jiǎn)化寫法 list.sort((g1, g2)-> g1.getPrice().compareTo(g2.getPrice()));
2.方法引用
方法引用通過方法的名字來指向一個(gè)方法。方法引用可以使語言的構(gòu)造更緊湊簡(jiǎn)潔,減少冗余代碼。方法引用使用一對(duì)冒號(hào) :: 。
Comparator<Girl> comparator = (g1, g2)-> g1.getPrice().compareTo(g2.getPrice()); //方法引用 Comparator.comparing(Girl::getPrice);
當(dāng)你需要方法引用時(shí),目標(biāo)引用放在分隔符::前,方法的名稱放在分隔符::后。
比如,上面的Girl::getPrice,就是引用了Mask中定義的getPrice方法。
方法名稱后不需要加括號(hào),因?yàn)槲覀儾]有實(shí)際調(diào)用它。
方法引用提高了代碼的可讀性,也使邏輯更加清晰,在一些stream流中,相信大家也經(jīng)常會(huì)用到。
例如:
List<String> collect = list.stream().map(Girl::getName).collect(Collectors.toList()); list.stream().forEach(System.out::println);
我們看到第一行通過Girl::getName方法引用,我們收集到了所有女孩的名字,那么第二行我們通過System.out::println打印出了list中的所有對(duì)象。
舉個(gè)栗子:
我們先改造一下實(shí)體類,增加了空參構(gòu)造函數(shù),增加了幾個(gè)方法,有靜態(tài)方法和非靜態(tài)方法。
@Data @AllArgsConstructor @NoArgsConstructor public class Girl { private String name; private Double size; private Double price; //Supplier是jdk1.8的接口,這里和lamda一起使用了 public static Girl create(final Supplier<Girl> supplier) { return supplier.get(); } public static void makeUp(final Girl girl) { System.out.println("化妝 " + girl.toString()); } public void follow(final Girl another) { System.out.println("Following the " + another.toString()); } public void dressUp() { System.out.println("更衣 " + this.toString()); } }
4種不同的方法引用
//構(gòu)造器引用:它的語法是Class::new,或者更一般的Class< T >::new實(shí)例如下: Girl girl = Girl.create(Girl::new); List<Girl> girls = Arrays.asList(girl); //靜態(tài)方法引用:它的語法是Class::static_method,實(shí)例如下: girls.forEach(Girl::makeUp); //特定類的任意對(duì)象的方法引用:它的語法是Class::method實(shí)例如下: girls.forEach(Girl::dressUp); //特定對(duì)象的方法引用:它的語法是instance::method實(shí)例如下: girls.forEach(girl::follow);
到這里,大家對(duì)lambda表達(dá)式應(yīng)該有了初步的認(rèn)識(shí),可以在平時(shí)編碼中多使用,畢竟實(shí)踐出真知??!
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Cloud Zipkin服務(wù)端追蹤服務(wù)
這篇文章主要介紹了Spring Cloud Zipkin服務(wù)端追蹤服務(wù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04Spring?Boot整合Log4j2.xml的問題及解決方法
這篇文章主要介紹了Spring?Boot整合Log4j2.xml的問題,本文給大家分享解決方案,需要的朋友可以參考下2023-09-09IDEA?Ui設(shè)計(jì)器JFormDesigner?永久激活插件+注冊(cè)機(jī)(親測(cè)一直在用)
這篇文章主要介紹了IDEA?Ui設(shè)計(jì)器JFormDesigner?永久激活----插件+注冊(cè)機(jī)?自己一直在用的版本和注冊(cè)機(jī),非常不錯(cuò),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08詳解如何用spring Restdocs創(chuàng)建API文檔
這篇文章將帶你了解如何用spring官方推薦的restdoc去生成api文檔。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05談?wù)凧ava中try-catch-finally中的return語句
我們知道return語句用在某一個(gè)方法中,一是用于返回函數(shù)的執(zhí)行結(jié)果,二是用于返回值為void類型的函數(shù)中,僅僅是一個(gè)return語句(return ;),此時(shí)用于結(jié)束方法的執(zhí)行,也即此return后的語句將不會(huì)被執(zhí)行,當(dāng)然,這種情況下return語句后不能再有其它的語句了2016-01-01java集成開發(fā)SpringBoot生成接口文檔示例實(shí)現(xiàn)
這篇文章主要為大家介紹了java集成開發(fā)SpringBoot如何生成接口文檔的示例實(shí)現(xiàn)過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10BeanFactory和FactoryBean的區(qū)別示例詳解
這篇文章主要為大家介紹了BeanFactory和FactoryBean的區(qū)別示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10mybatis自動(dòng)填充時(shí)間字段示例代碼
這篇文章主要給大家介紹了關(guān)于mybatis自動(dòng)填充時(shí)間字段的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01