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