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