Java SE 8新特性导览:使用Lambda Expression进行函数式编程
“ Java SE 8新功能瀏覽 ”系列的這篇文章將深入了解Lambda表達(dá)式 。 我將向您展示Lambda表達(dá)式的幾種不同用法。 它們都具有功能接口的共同實(shí)現(xiàn)。 我將解釋編譯器如何從代碼中推斷信息,例如特定類型的變量以及后臺(tái)實(shí)際發(fā)生的情況。
在上一篇文章“ Java SE 8新功能之旅:Java開發(fā)世界中的重大變化 ”中,我談到了在本系列文章中我們將要探索的內(nèi)容。 首先介紹Java SE 8的 主要功能 ,然后介紹在Microsoft Windows和Apple Mac OS X平臺(tái)上JDK8的安裝過程 ,并提供重要的建議和注意事項(xiàng)。
最后,我們經(jīng)歷了一個(gè)由Lambda表達(dá)式支持的控制臺(tái)應(yīng)用程序的開發(fā),以確保我們可能已經(jīng)安裝了Java SE 8。
源代碼托管在我的Github帳戶上:從此處克隆。
Lambda表達(dá)是什么?
Java SE 8最著名的新功能也許叫做Project Lambda,它是將Java引入函數(shù)式編程領(lǐng)域的一項(xiàng)努力。
用計(jì)算機(jī)科學(xué)術(shù)語;
Lambda是一個(gè)匿名函數(shù)。 即,沒有名稱的功能。
在Java中;
所有函數(shù)都是類的成員,被稱為方法。 要?jiǎng)?chuàng)建方法,您需要定義其所屬的類。
Java SE 8中的lambda表達(dá)式使您可以使用非常簡潔的語法定義一個(gè)類和單個(gè)方法,以實(shí)現(xiàn)具有單個(gè)抽象方法的接口。
讓我們弄清楚這個(gè)想法。
Lambda Expressions使開發(fā)人員可以簡化和縮短其代碼。 使它更具可讀性和可維護(hù)性。 這將導(dǎo)致刪除更多詳細(xì)的類聲明 。
讓我們看一些代碼片段。
在此示例中,我的實(shí)現(xiàn)將文字字符串輸出到控制臺(tái)。 然后,您將獲取該對象,并將其傳遞給線程類的實(shí)例。 我將可運(yùn)行對象實(shí)例化為名為r1的對象。 將其傳遞給線程的構(gòu)造函數(shù)并調(diào)用線程的start方法。 我的代碼現(xiàn)在將在自己的線程和內(nèi)存空間中運(yùn)行。
所以現(xiàn)在,我再次創(chuàng)建一個(gè)名為r1的對象,但直接調(diào)用該接口的構(gòu)造方法。 再一次,實(shí)現(xiàn)它是單個(gè)抽象方法。 然后,我將對象傳遞給線程的構(gòu)造函數(shù)。
我正在聲明具有可運(yùn)行類型的對象,但現(xiàn)在我使用一行代碼來聲明單個(gè)抽象方法實(shí)現(xiàn),然后再次將對象傳遞給線程的構(gòu)造函數(shù)。 您仍在實(shí)現(xiàn)可運(yùn)行的接口并調(diào)用它的run方法,但使用的代碼卻少得多。 此外,它可以進(jìn)行以下改進(jìn):
public static void main(String[] args) { new Thread(() -> System.out.println("I am running")).start(); }這是有關(guān)Lambda項(xiàng)目的早期規(guī)格文檔中的重要報(bào)價(jià)。
Lambda表達(dá)式只能出現(xiàn)在將它們分配給類型為功能接口的變量的位置。
引用布萊恩·格茨
讓我們分解一下以了解發(fā)生了什么。
有哪些功能接口?
功能接口是僅具有一個(gè)自定義抽象方法的接口。 即,不是從對象類繼承的對象。 Java有許多這樣的接口,例如Runnable,Comparable,Callable,TimerTask等。
在Java 8之前,它們被稱為Single Abstract Method或SAM接口 。 在Java 8中,我們現(xiàn)在將它們稱為功能接口 。
Lambda表達(dá)式語法:
這個(gè)lambda表達(dá)式返回了runnable接口的實(shí)現(xiàn)。 它有兩部分,由稱為箭頭標(biāo)記或Lambda運(yùn)算符的新語法分開。 lambda表達(dá)式的第一部分,在箭頭標(biāo)記之前,是您要實(shí)現(xiàn)的方法的簽名。
在此示例中,這是一個(gè)無參數(shù)方法,因此僅用括號(hào)表示。 但是,如果我要實(shí)現(xiàn)一個(gè)接受參數(shù)的方法,則只需給出參數(shù)名稱。 我不必聲明它們的類型。
因?yàn)榻涌谥挥幸粋€(gè)抽象方法,所以數(shù)據(jù)類型是已知的。 lambda表達(dá)式的目標(biāo)之一就是消除不必要的語法。 表達(dá)式的第二部分,在箭頭標(biāo)記之后,是單個(gè)方法主體的實(shí)現(xiàn)。
如果僅是一行代碼(如本例所示),則您不需要任何其他內(nèi)容。 要使用多個(gè)語句實(shí)現(xiàn)方法主體, 請將它們括在花括號(hào)中 。
Runnable r = ( ) -> {System.out.println("Hello!");System.out.println("Lambda!");};Lambda目標(biāo):
Lambda表達(dá)式可以減少您需要編寫的代碼量以及必須創(chuàng)建和維護(hù)的自定義類的數(shù)量。
如果您要實(shí)現(xiàn)一次使用的接口,那么創(chuàng)建另一個(gè)代碼文件或另一個(gè)命名類并不總是很有意義。 Lambda表達(dá)式可以定義一次匿名實(shí)現(xiàn),以供一次性使用,并顯著簡化代碼。
定義和實(shí)例化功能接口
為了開始學(xué)習(xí)Lambda表達(dá)式,我將創(chuàng)建一個(gè)全新的功能接口。 一個(gè)具有單個(gè)抽象方法的接口,然后我將使用Lambda表達(dá)式實(shí)現(xiàn)該接口。
您可以使用托管在github上的源代碼項(xiàng)目“ JavaSE8-Features”來導(dǎo)航項(xiàng)目代碼。
沒有任何參數(shù)的方法,Lambda實(shí)現(xiàn)
在我的源代碼中,我實(shí)際上將接口放入其自己的以lambda.interfaces結(jié)尾的子包中。 我將其命名為HelloInterface接口。為了實(shí)現(xiàn)帶有l(wèi)ambda表達(dá)式的接口,它必須具有一個(gè)抽象方法。 我將聲明一個(gè)返回void的公共方法,并將其命名為doGreeting 。 它不會(huì)接受任何參數(shù),這是使接口可用于Lambda表達(dá)式所需要做的全部工作。 如果需要,可以使用新的注釋,該注釋已添加到Java SE 8中,稱為功能接口 。
/**** @author mohamed_taman*/ @FunctionalInterface public interface HelloInterface {void doGreeting();}現(xiàn)在,我準(zhǔn)備在lambda.impl包下創(chuàng)建一個(gè)新類UseHelloInterface , 該類將實(shí)例化我的功能接口( HelloInterface ),如下所示:
/*** @author mohamed_taman*/public class UseHelloInterface {public static void main(String[] args) {HelloInterface hello = ()-> out.println("Hello from Lambda expression");hello.doGreeting();} }運(yùn)行文件并檢查結(jié)果,它應(yīng)該運(yùn)行并輸出以下內(nèi)容。
------------------------------------------------------------------------------------ --- exec-maven-plugin:1.2.1:exec (default-cli) @ Java8Features --- Hello from Lambda expression ------------------------------------------------------------------------------------因此,當(dāng)您使用不接受任何參數(shù)的單個(gè)抽象方法時(shí),代碼就是這樣。 讓我們看一下帶有參數(shù)的外觀。
具有任何參數(shù)的方法,Lambda實(shí)現(xiàn)
在lambda.interfaces下 。 我將創(chuàng)建一個(gè)新接口,并將其命名為CalculatorInterface 。 然后,我將聲明一個(gè)返回void的公共方法,并將其命名為doCalculate ,它將接收兩個(gè)整數(shù)參數(shù)value1和value2 。
/*** @author mohamed_taman*/@FunctionalInterface public interface CalculatorInterface {public void doCalculate(int value1, int value2);}現(xiàn)在,我準(zhǔn)備在lambda.impl包下創(chuàng)建一個(gè)新類Use CalculatorInterface ,它將實(shí)例化我的功能接口( CalculatorInterface ),如下所示:
public static void main(String[] args) {CalculatorInterface calc = (v1, v2) -> {int result = v1 * v2;out.println("The calculation result is: "+ result);};calc.doCalculate(10, 5);}請注意doCalculate()參數(shù),它們在接口中分別命名為value1和value2,但是您可以在此處為它們命名。 我將其命名為v1和v2。 我不需要在參數(shù)名稱前插入int; 該信息是已知的,因?yàn)榫幾g器可以從功能接口方法簽名中推斷出此信息。運(yùn)行文件并檢查結(jié)果,它應(yīng)該運(yùn)行并輸出以下內(nèi)容。
------------------------------------------------------------------------------------ --- exec-maven-plugin:1.2.1:exec (default-cli) @ Java8Features --- The calculation result is: 50 ------------------------------------------------------------------------------------ BUILD SUCCESS始終牢記以下規(guī)則:
同樣,您必須遵循該規(guī)則,即接口只能具有一個(gè)抽象方法 。 然后,可以使用lambda表達(dá)式實(shí)現(xiàn)該接口及其單一抽象方法。
將內(nèi)置功能接口與lambda結(jié)合使用
前面已經(jīng)介紹了如何使用lambda表達(dá)式實(shí)現(xiàn)您自己創(chuàng)建的接口。現(xiàn)在,我將展示具有內(nèi)置接口的lambda表達(dá)式。 屬于Java運(yùn)行時(shí)的接口。 我將使用兩個(gè)示例。 我正在一個(gè)名為lambda.builtin的程序包中工作,這是練習(xí)文件的一部分。 我將從這堂課開始。 UseThreading 。 在此類中,我實(shí)現(xiàn)了Runnable接口。 這個(gè)接口是Java多線程體系結(jié)構(gòu)的一部分,我的重點(diǎn)是代碼的編寫方式,而不是操作方式。 我將展示如何使用lambda表達(dá)式替換這些內(nèi)部類。 我將注釋掉聲明兩個(gè)對象的代碼。 然后,我將重新聲明它們并使用lambdas進(jìn)行實(shí)現(xiàn)。 因此,讓我們開始吧。
public static void main(String[] args) {//Old version// Runnable thrd1 = new Runnable(){// @Override // public void run() { // out.println("Hello Thread 1."); // } //};/******************************************* Using lambda expression inner classes *******************************************/Runnable thrd1 = () -> out.println("Hello Thread 1.");new Thread(thrd1).start();// Old Version/*new Thread(new Runnable() {@Overridepublic void run() {out.println("Hello Thread 2.");}}).start();*//******************************************** Using lambda expression anonymous class ********************************************/new Thread(() -> out.println("Hello Thread 2.")).start();}讓我們看另一個(gè)例子。 我將使用比較器 。 比較器是Java中的另一個(gè)功能接口,具有單個(gè)抽象方法。 此方法是比較方法。打開文件UseComparator類,并檢查代碼的注釋位,這是實(shí)際代碼,然后將其重構(gòu)為lambda表達(dá)式。
public static void main(String[] args) {List<string> values = new ArrayList();values.add("AAA");values.add("bbb");values.add("CCC");values.add("ddd");values.add("EEE");//Case sensitive sort operationsort(values);out.println("Simple sort:");print(values);// Case insensetive sort operation with anonymous class/* Collections.sort(values, new Comparator<string>() {@Overridepublic int compare(String o1, String o2) {return o1.compareToIgnoreCase(o2);}}); */// Case insensetive sort operation with Lambdasort(values,(o1, o2) -> o1.compareToIgnoreCase(o2));out.println("Sort with Comparator");print(values);}和以前一樣,它不會(huì)為您提供任何性能優(yōu)勢 。 基本功能完全相同。 無論您聲明自己的類 ,使用內(nèi)部或匿名內(nèi)部類還是lambda表達(dá)式 ,完全取決于您。
在本系列的下一篇文章中,我們將探討和代碼如何使用lambda表達(dá)式, 過濾與謂詞接口的集合 , 遍歷與方法引用 的集合 ,在接口實(shí)現(xiàn)的默認(rèn)方法,并最終實(shí)現(xiàn)在接口的靜態(tài)方法 遍歷集合 。
資源:
翻譯自: https://www.javacodegeeks.com/2014/07/java-se-8-new-features-tour-functional-programming-with-lambda-expression.html
總結(jié)
以上是生活随笔為你收集整理的Java SE 8新特性导览:使用Lambda Expression进行函数式编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑版奶块闪退(电脑奶块闪退怎么办)
- 下一篇: 充电桩设置(斑马智行充电桩设置)