摘要:的本質(zhì)需求按照產(chǎn)品的重量進(jìn)行升序排序此處使用匿名內(nèi)部類的設(shè)計(jì),但摻雜了較多的語(yǔ)法噪聲,引入了不必要的復(fù)雜度。使用表達(dá)式,可以進(jìn)一步消除語(yǔ)法噪聲,簡(jiǎn)化設(shè)計(jì)。方法引用其本質(zhì)是具有單一方法調(diào)用的表達(dá)式的語(yǔ)法糖表示。
Lambda的本質(zhì)
需求1. 按照產(chǎn)品的重量進(jìn)行升序排序
此處使用「匿名內(nèi)部類」的設(shè)計(jì),但摻雜了較多的語(yǔ)法噪聲,引入了不必要的復(fù)雜度。
Collections.sort(repo, new Comparator() { @Override public int compare(Product p1, Product p2) { return p1.getWeight().compareTo(p2.getWeight()); } });
使用Lambda表達(dá)式,可以進(jìn)一步消除語(yǔ)法噪聲,簡(jiǎn)化設(shè)計(jì)。
Collections.sort(repo, (Product p1, Product p2) -> p1.getWeight().compareTo(p2.getWeight()));
也就是說(shuō),Lambda其本質(zhì)是「匿名內(nèi)部類」的一種「語(yǔ)法糖」表示,存在如下3個(gè)方面的特征:
Anonymous Function:匿名的函數(shù)
Passed Around:可作為參數(shù)或返回值進(jìn)行傳遞,甚至可以自由地存儲(chǔ)在變量中
Concise:相對(duì)于匿名內(nèi)部類的樣板代碼(Boilerplate),Lambda更加簡(jiǎn)潔漂亮
類型推演借助編譯器「類型推演」的能力,可以進(jìn)一步簡(jiǎn)化Lambda表達(dá)式。
Collections.sort(repo, (p1, p2) -> p1.getWeight().compareTo(p2.getWeight()));Lambda的形式
形式1:(parameters) -> expression
Collections.sort(repo, (p1, p2) -> p1.getWeight().compareTo(p2.getWeight()));
形式2:(parameters) -> { statements; }
Collections.sort(repo, (p1, p2) -> { return p1.getWeight().compareTo(p2.getWeight()); });默認(rèn)方法
先看看java.util.Collections.sort的實(shí)現(xiàn),其中java.util.Collections是一個(gè)典型的「工具類」。
public final class Collectins { private Collectins() { } public staticvoid sort(List extends T> l, Comparator super T> c) { l.sort(c); } }
這樣的設(shè)計(jì)是反OO,為此可以將其sort搬遷至List接口中去。
public interface Listextends Collection { default void sort(Comparator super E> c) { ... } ... }
default方法類似于C++的虛函數(shù)。從某種意義上看,default的引入使得Java又重新回到了「多重繼承」的懷抱,為設(shè)計(jì)帶來(lái)了更大的彈性。
為此,設(shè)計(jì)可重構(gòu)為更加符合OO的風(fēng)格。
repo.sort((p1, p2) -> p1.getWeight().compareTo(p2.getWeight()));方法引用
借助Comparator.comparing的工廠方法,結(jié)合「方法引用」可進(jìn)一步提高代碼的可讀性。
import static java.util.Comparator.comparing; repo.sort(comparing(Product::getWeight));
方法引用其本質(zhì)是具有單一方法調(diào)用的lambda表達(dá)式的「語(yǔ)法糖」表示。
級(jí)聯(lián)方法需求2. 按照產(chǎn)品的重量降序排序
repo.sort(comparing(Product::getWeight) .reversed()); .thenComparing(Product::getCountry));
需求3. 如果重量相同,則按照出廠國(guó)的自然序排序
repo.sort(comparing(Product::getWeight) .reversed() .thenComparing(Product::getCountry));深入理解Comparator
有且僅有一個(gè)抽象方法的接口,稱為「函數(shù)式接口」,使用@FunctionalInterface的注解標(biāo)識(shí)。函數(shù)式接口中「抽象方法」描述了Lambda表達(dá)式的「原型」。
() -> {}也是一個(gè)合法的Lambda表達(dá)式,與Runnable接口相匹配。
也就是說(shuō),一個(gè)「函數(shù)式接口」可包含如下元素:
Abstract Method:有且僅有一個(gè)抽象方法
Default Methods:0個(gè)或多個(gè)默認(rèn)方法
Static Methods: 0個(gè)或多個(gè)靜態(tài)方法
對(duì)照前面的列子,可洞悉Comparator設(shè)計(jì)的巧妙。
repo.sort(comparing(Product::getWeight) .reversed());
其中,Comparator就是一個(gè)典型的函數(shù)式接口。通過(guò)「方法級(jí)聯(lián)」設(shè)計(jì)了一套簡(jiǎn)單的Comparator的DSL,增強(qiáng)了用戶的表達(dá)力。
@FunctionalInterface public interface Comparator{ int compare(T o1, T o2); default Comparator reversed() { return Collections.reverseOrder(this); } static > Comparator comparing( Function super T, ? extends U> extractor) { return (c1, c2) -> extractor.apply(c1) .compareTo(extractor.apply(c2)); } }
其中,Comprator.compring的實(shí)現(xiàn)稍微有點(diǎn)復(fù)雜。
comparing是一個(gè)靜態(tài)工廠方法,它生產(chǎn)一個(gè)Comparator
comparing是一個(gè)高階函數(shù);
接受一個(gè)函數(shù):Function super T, ? extends U> extractor
返回一個(gè)函數(shù):Comparator
comparing是一個(gè)語(yǔ)法糖,結(jié)合「方法引用」的機(jī)制,極大地改善了用戶接口的表達(dá)力;
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/65723.html
摘要:局部變量表達(dá)式的方法體與嵌套代碼塊有著相同的作用域。在表達(dá)式中不允許聲明一個(gè)與局部變量同名的參數(shù)或者局部變量。不可變的約束只作用在局部變量上,如果是一個(gè)實(shí)例變量或者閉合類的靜態(tài)變量,那么不會(huì)有任何錯(cuò)誤被報(bào)告出來(lái)即使結(jié)果同樣未定義。 完整的Java學(xué)習(xí)的路線圖可以參考:我的編程之路--知識(shí)管理與知識(shí)體系 Lambda&Closures Java8 Lambda表達(dá)式10個(gè)示例 閉包一般指...
摘要:一表達(dá)式匿名內(nèi)部類最大的問(wèn)題在于其冗余的語(yǔ)法,比如前面的中五行代碼僅有一行是在執(zhí)行任務(wù)??偨Y(jié)基于詞法作用域的理念,表達(dá)式不可以掩蓋任何其所在上下文的局部變量。 轉(zhuǎn)載請(qǐng)注明出處:https://zhuanlan.zhihu.com/p/20540175 在介紹Lambda表達(dá)式之前,我們先來(lái)看只有單個(gè)方法的Interface(通常我們稱之為回調(diào)接口): public interface...
摘要:之前,使用匿名類給蘋果排序的代碼是的,這段代碼看上去并不是那么的清晰明了,使用表達(dá)式改進(jìn)后或者是不得不承認(rèn),代碼看起來(lái)跟清晰了。這是由泛型接口內(nèi)部實(shí)現(xiàn)方式造成的。 # Lambda表達(dá)式在《Java8實(shí)戰(zhàn)》中第三章主要講的是Lambda表達(dá)式,在上一章節(jié)的筆記中我們利用了行為參數(shù)化來(lái)因?qū)Σ粩嘧兓男枨?,最后我們也使用到了Lambda,通過(guò)表達(dá)式為我們簡(jiǎn)化了很多代碼從而極大地提高了我們的...
大概一年多之前,我對(duì)java8的理解還僅限一些只言片語(yǔ)的文章之上,后來(lái)出于對(duì)函數(shù)式編程的興趣,買了本參考書看了一遍,然后放在了書架上,后來(lái),當(dāng)我接手大客戶應(yīng)用的開(kāi)發(fā)工作之后,java8的一些工具,對(duì)我的效率有了不小的提升,因此想記錄一下java8的一些常用場(chǎng)景,我希望這會(huì)成為一個(gè)小字典,能讓我免于頻繁翻書,但是總能找到自己想找的知識(shí)。 用于舉例的model: @Data public class ...
摘要:引入了與此前完全不同的函數(shù)式編程方法,通過(guò)表達(dá)式和來(lái)為下的函數(shù)式編程提供動(dòng)力。命令式編程語(yǔ)言把對(duì)象變量和流轉(zhuǎn)當(dāng)作一等公民,而函數(shù)式編程在此基礎(chǔ)上加入了策略變量這一新的一等公民。 Java8引入了與此前完全不同的函數(shù)式編程方法,通過(guò)Lambda表達(dá)式和StreamAPI來(lái)為Java下的函數(shù)式編程提供動(dòng)力。本文是Java8新特性的第一篇,旨在闡釋函數(shù)式編程的本義,更在展示Java是如何通...
閱讀 4189·2021-09-22 15:34
閱讀 2802·2021-09-22 15:29
閱讀 521·2019-08-29 13:52
閱讀 3375·2019-08-29 11:30
閱讀 2301·2019-08-26 10:40
閱讀 869·2019-08-26 10:19
閱讀 2283·2019-08-23 18:16
閱讀 2352·2019-08-23 17:50