日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java lambda expression

發(fā)布時(shí)間:2025/3/15 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java lambda expression 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Lambda表達(dá)式

匿名類的一個(gè)問(wèn)題是,如果匿名類的實(shí)現(xiàn)非常簡(jiǎn)單,例如只包含一個(gè)方法的接口,那么匿名類的語(yǔ)法可能看起來(lái)不實(shí)用且不清楚。在這些情況下,您通常會(huì)嘗試將功能作為參數(shù)傳遞給另一個(gè)方法,例如當(dāng)有人單擊按鈕時(shí)應(yīng)采取的操作。Lambda表達(dá)式使您可以執(zhí)行此操作,將功能視為方法參數(shù),或?qū)⒋a視為數(shù)據(jù)。

一頁(yè)???小道???下一頁(yè)?

Java教程是為JDK 8編寫(xiě)的。本頁(yè)描述的示例和實(shí)踐沒(méi)有利用后續(xù)版本中引入的改進(jìn)。

Lambda表達(dá)式

匿名類的一個(gè)問(wèn)題是,如果匿名類的實(shí)現(xiàn)非常簡(jiǎn)單,例如只包含一個(gè)方法的接口,那么匿名類的語(yǔ)法可能看起來(lái)不實(shí)用且不清楚。在這些情況下,您通常會(huì)嘗試將功能作為參數(shù)傳遞給另一個(gè)方法,例如當(dāng)有人單擊按鈕時(shí)應(yīng)采取的操作。Lambda表達(dá)式使您可以執(zhí)行此操作,將功能視為方法參數(shù),或?qū)⒋a視為數(shù)據(jù)。

上一節(jié)“?匿名類?”向您展示了如何在不給它命名的情況下實(shí)現(xiàn)基類。雖然這通常比命名類更簡(jiǎn)潔,但對(duì)于只有一個(gè)方法的類,即使是匿名類也似乎有點(diǎn)過(guò)分和繁瑣。Lambda表達(dá)式允許您更緊湊地表達(dá)單方法類的實(shí)例。

Lambda表達(dá)式的理想用例

假設(shè)您正在創(chuàng)建社交網(wǎng)絡(luò)應(yīng)用程序。您希望創(chuàng)建一項(xiàng)功能,使管理員能夠?qū)M足特定條件的社交網(wǎng)絡(luò)應(yīng)用程序成員執(zhí)行任何類型的操作,例如發(fā)送消息。下表詳細(xì)描述了此用例:

領(lǐng)域描述
名稱對(duì)選定的成員執(zhí)行操作
主要演員管理員
前提條件管理員已登錄系統(tǒng)。
后置條件僅對(duì)符合指定條件的成員執(zhí)行操作。
主要成功案例
  • 管理員指定要執(zhí)行特定操作的成員的條件。
  • 管理員指定要對(duì)這些選定成員執(zhí)行的操作。
  • 管理員選擇“?提交”按鈕。
  • 系統(tǒng)將查找與指定條件匹配的所有成員。
  • 系統(tǒng)對(duì)所有匹配成員執(zhí)行指定的操作。
  • 擴(kuò)展

    1A。管理員可以選擇在指定要執(zhí)行的操作之前或選擇“?提交”按鈕之前預(yù)覽符合指定條件的成員。

    發(fā)生頻率白天很多次。

    假設(shè)此社交網(wǎng)絡(luò)應(yīng)用程序的成員由以下Person類表示?:

    公共類人{(lán)public enum Sex {男,女}字符串名稱;LocalDate生日;性別;字符串emailAddress;public int getAge(){// ...}public void printPerson(){// ...} }

    假設(shè)您的社交網(wǎng)絡(luò)應(yīng)用程序的成員存儲(chǔ)在一個(gè)List<Person>實(shí)例中。方法我介紹一種,其他的可以查看其官網(wǎng)。

    創(chuàng)建搜索匹配一個(gè)特征的成員的方法

    一種簡(jiǎn)單的方法是創(chuàng)建幾種方法;?每種方法都會(huì)搜索與一個(gè)特征匹配的成員,例如性別或年齡。以下方法打印超過(guò)指定年齡的成員:

    public static void printPersonsOlderThan(List <Person> roster,int age){for(Person p:roster){if(p.getAge()> = age){p.printPerson();}} }

    注意:A?List是有序的?Collection。甲集合是一個(gè)對(duì)象,該組中的多個(gè)元素到單個(gè)單元中。集合用于存儲(chǔ),檢索,操作和傳遞聚合數(shù)據(jù)。有關(guān)集合的更多信息,請(qǐng)參閱?集合跟蹤。

    這種方法可能會(huì)使您的應(yīng)用程序變得脆弱,這是由于引入了更新(例如更新的數(shù)據(jù)類型)導(dǎo)致應(yīng)用程序無(wú)法工作的可能性。假設(shè)您升級(jí)應(yīng)用程序并更改Person類的結(jié)構(gòu),使其包含不同的成員變量;?也許該類記錄和測(cè)量年齡與不同的數(shù)據(jù)類型或算法。您必須重寫(xiě)大量API以適應(yīng)此更改。此外,這種方法是不必要的限制;?例如,如果您想要打印年齡小于某個(gè)年齡的成員,該怎么辦?

    Lambda表達(dá)式的語(yǔ)法

    lambda表達(dá)式包含以下內(nèi)容:

    • 括號(hào)中用逗號(hào)分隔的形式參數(shù)列表。該CheckPerson.test方法包含一個(gè)參數(shù),?p表示Person該類的實(shí)例?。

      注意:您可以省略lambda表達(dá)式中參數(shù)的數(shù)據(jù)類型。此外,如果只有一個(gè)參數(shù),則可以省略括號(hào)。例如,以下lambda表達(dá)式也是有效的:

      p - > p.getGender()== Person.Sex.MALE && p.getAge()> = 18&& p.getAge()<= 25
    • 箭頭標(biāo)記,?->

    • 一個(gè)主體,由單個(gè)表達(dá)式或語(yǔ)句塊組成。此示例使用以下表達(dá)式:

      p.getGender()== Person.Sex.MALE && p.getAge()> = 18&& p.getAge()<= 25

      如果指定單個(gè)表達(dá)式,則Java運(yùn)行時(shí)將計(jì)算表達(dá)式,然后返回其值。或者,您可以使用return語(yǔ)句:

      p - > {return p.getGender()== Person.Sex.MALE&& p.getAge()> = 18&& p.getAge()<= 25; }

      return語(yǔ)句不是表達(dá)式;?在lambda表達(dá)式中,必須用braces({})括起語(yǔ)句。但是,您不必在大括號(hào)中包含void方法調(diào)用。例如,以下是有效的lambda表達(dá)式:

      電子郵件 - > System.out.println(電子郵件)

    請(qǐng)注意,lambda表達(dá)式看起來(lái)很像方法聲明;?您可以將lambda表達(dá)式視為匿名方法 - 沒(méi)有名稱的方法。

    以下示例?Calculator是一個(gè)lambda表達(dá)式的示例,它采用多個(gè)形式參數(shù):

    公共類計(jì)算器{interface IntegerMath {int operation(int a,int b); }public int operateBinary(int a,int b,IntegerMath op){return op.operation(a,b);}public static void main(String ... args){計(jì)算器myApp = new Calculator();IntegerMath add =(a,b) - > a + b;IntegerMath減法=(a,b) - > a - b;System.out.println(“40 + 2 =”+myApp.operateBinary(40,2,另外));System.out.println(“20 - 10 =”+myApp.operateBinary(20,10,減法)); } }

    該方法operateBinary對(duì)兩個(gè)整數(shù)操作數(shù)執(zhí)行數(shù)學(xué)運(yùn)算。操作本身由實(shí)例指定IntegerMath。的例子中定義了lambda表達(dá)式兩個(gè)操作,addition和subtraction。該示例打印以下內(nèi)容:

    40 + 2 = 42 20 - 10 = 10

    訪問(wèn)封閉范圍的局部變量

    像本地和匿名類一樣,lambda表達(dá)式可以?捕獲變量?;?它們對(duì)封閉范圍的局部變量具有相同的訪問(wèn)權(quán)限。但是,與本地和匿名類不同,lambda表達(dá)式?jīng)]有任何陰影問(wèn)題(有關(guān)更多信息,請(qǐng)參閱?陰影)。Lambda表達(dá)式是詞法范圍的。這意味著它們不會(huì)從超類型繼承任何名稱或引入新級(jí)別的范圍。lambda表達(dá)式中的聲明與封閉環(huán)境中的聲明一樣被解釋。以下示例?LambdaScopeTest演示了這一點(diǎn):

    import java.util.function.Consumer;公共類LambdaScopeTest {public int x = 0;class FirstLevel {public int x = 1;void methodInFirstLevel(int x){//以下語(yǔ)句導(dǎo)致編譯器生成//錯(cuò)誤“從lambda表達(dá)式引用的局部變量//必須是最終的或有效的最終“在聲明A中://// x = 99;消費(fèi)者<整數(shù)> myConsumer =(y) - > {System.out.println(“x =”+ x); //聲明A.System.out.println(“y =”+ y);System.out.println(“this.x =”+ this.x);System.out.println(“LambdaScopeTest.this.x =”+LambdaScopeTest.this.x);};myConsumer.accept(X);}}public static void main(String ... args){LambdaScopeTest st = new LambdaScopeTest();LambdaScopeTest.FirstLevel fl = st.new FirstLevel();fl.methodInFirstLevel(23);} }

    此示例生成以下輸出:

    x = 23 y = 23 this.x = 1 LambdaScopeTest.this.x = 0

    如果在lambda表達(dá)式的聲明中替換參數(shù)x代替,則編譯器會(huì)生成錯(cuò)誤:ymyConsumer

    消費(fèi)者<整數(shù)> myConsumer =(x) - > {// ... }

    編譯器生成錯(cuò)誤“變量x已在方法methodInFirstLevel(int)中定義”,因?yàn)閘ambda表達(dá)式不會(huì)引入新的作用域級(jí)別。因此,您可以直接訪問(wèn)封閉范圍的字段,方法和局部變量。例如,lambda表達(dá)式直接訪問(wèn)x方法的參數(shù)methodInFirstLevel。要訪問(wèn)封閉類中的變量,請(qǐng)使用關(guān)鍵字this。在此示例中,this.x引用成員變量FirstLevel.x。

    但是,與本地和匿名類一樣,lambda表達(dá)式只能訪問(wèn)最終或有效最終的封閉塊的局部變量和參數(shù)。例如,假設(shè)您在methodInFirstLevel定義語(yǔ)句后立即添加以下賦值語(yǔ)句:

    void methodInFirstLevel(int x){x = 99;// ... }

    由于這個(gè)賦值語(yǔ)句,變量FirstLevel.x不再是有效的最終結(jié)果。因此,Java編譯器生成類似于“從lambda表達(dá)式引用的局部變量必須是final或者final final”的錯(cuò)誤消息,其中l(wèi)ambda表達(dá)式myConsumer嘗試訪問(wèn)FirstLevel.x變量:

    System.out.println(“x =”+ x);

    目標(biāo)打字

    你如何確定lambda表達(dá)式的類型?回想一下lambda表達(dá)式,它選擇了男性和年齡在18到25歲之間的成員:

    p - > p.getGender()== Person.Sex.MALE&& p.getAge()> = 18&& p.getAge()<= 25

    這個(gè)lambda表達(dá)式用于以下兩種方法:

    • public static void printPersons(List<Person> roster, CheckPerson tester)在方法3:在局部類指定搜索條件碼

    • public void printPersonsWithPredicate(List<Person> roster, Predicate<Person> tester)在方法6:Lambda表達(dá)式使用標(biāo)準(zhǔn)的功能接口

    當(dāng)Java運(yùn)行時(shí)調(diào)用該方法時(shí)printPersons,它期望數(shù)據(jù)類型為CheckPerson,因此lambda表達(dá)式屬于此類型。但是,當(dāng)Java運(yùn)行時(shí)調(diào)用該方法時(shí)printPersonsWithPredicate,它期望數(shù)據(jù)類型為Predicate<Person>,因此lambda表達(dá)式屬于此類型。這些方法所期望的數(shù)據(jù)類型稱為目標(biāo)類型。要確定lambda表達(dá)式的類型,Java編譯器將使用發(fā)現(xiàn)lambda表達(dá)式的上下文或情境的目標(biāo)類型。因此,您只能在Java編譯器可以確定目標(biāo)類型的情況下使用lambda表達(dá)式:

    • 變量聲明

    • 分配

    • 退貨聲明

    • 數(shù)組初始化器

    • 方法或構(gòu)造函數(shù)參數(shù)

    • Lambda表達(dá)體

    • 條件表達(dá)式,??:

    • 轉(zhuǎn)換表達(dá)式

    目標(biāo)類型和方法參數(shù)

    對(duì)于方法參數(shù),Java編譯器使用另外兩種語(yǔ)言特性確定目標(biāo)類型:重載解析和類型參數(shù)推斷。

    考慮以下兩個(gè)功能接口(?java.lang.Runnable和?java.util.concurrent.Callable<V>):

    public interface Runnable {void run(); }公共接口Callable <V> {V call(); }

    該方法Runnable.run不返回值,而是返回值Callable<V>.call。

    假設(shè)您已invoke按如下方式重載方法(有關(guān)重載方法的詳細(xì)信息,請(qǐng)參閱?定義方法):

    void invoke(Runnable r){r.run(); }<T> T invoke(Callable <T> c){return c.call(); }

    將在以下語(yǔ)句中調(diào)用哪個(gè)方法?

    String s = invoke(() - >“done”);

    該方法invoke(Callable<T>)將被調(diào)用因?yàn)樵摲椒ǚ祷氐闹??方法?invoke(Runnable)沒(méi)有。在這種情況下,lambda表達(dá)式的類型() -> "done"是Callable<T>。

    序列化

    如果lambda表達(dá)式的目標(biāo)類型及其捕獲的參數(shù)是可序列化的,則可以?序列化它。但是,與?內(nèi)部類一樣,強(qiáng)烈建議不要對(duì)lambda表達(dá)式進(jìn)行序列化。

    各種方法參考

    有四種方法參考:

    類例
    參考靜態(tài)方法ContainingClass::staticMethodName
    引用特定對(duì)象的實(shí)例方法containingObject::instanceMethodName
    引用特定類型的任意對(duì)象的實(shí)例方法ContainingType::methodName
    引用構(gòu)造函數(shù)ClassName::new

    參考靜態(tài)方法

    方法引用Person::compareByAge是對(duì)靜態(tài)方法的引用。

    引用特定對(duì)象的實(shí)例方法

    以下是對(duì)特定對(duì)象的實(shí)例方法的引用示例:

    class ComparisonProvider {public int compareByName(Person a,Person b){return a.getName()。compareTo(b.getName());}public int compareByAge(Person a,Person b){return a.getBirthday()。compareTo(b.getBirthday());} } ComparisonProvider myComparisonProvider = new ComparisonProvider(); Arrays.sort(rosterAsArray,myComparisonProvider :: compareByName);

    方法引用myComparisonProvider::compareByName調(diào)用compareByName作為對(duì)象一部分的方法myComparisonProvider。JRE推斷出方法類型參數(shù),在本例中是(Person, Person)。

    對(duì)特定類型的任意對(duì)象的實(shí)例方法的引用

    以下是對(duì)特定類型的任意對(duì)象的實(shí)例方法的引用示例:

    String [] stringArray = {“芭芭拉”,“詹姆斯”,“瑪麗”,“約翰”,“Patricia”,“Robert”,“Michael”,“Linda”}; Arrays.sort(stringArray,String :: compareToIgnoreCase);

    方法引用的等效lambda表達(dá)式String::compareToIgnoreCase將具有形式參數(shù)列表(String a, String b),其中a和b是用于更好地描述此示例的任意名稱。方法引用將調(diào)用該方法a.compareToIgnoreCase(b)。

    參考構(gòu)造函數(shù)

    您可以使用名稱以與靜態(tài)方法相同的方式引用構(gòu)造函數(shù)new。以下方法將元素從一個(gè)集合復(fù)制到另一個(gè)集合:

    public static <T,SOURCE擴(kuò)展Collection <T>,DEST擴(kuò)展Collection <T >>DEST transferElements(SOURCE sourceCollection,供應(yīng)商<DEST> collectionFactory){DEST result = collectionFactory.get();for(T t:sourceCollection){result.add(T);}返回結(jié)果; }

    功能接口Supplier包含一個(gè)get不帶參數(shù)并返回對(duì)象的方法。因此,您可以transferElements使用lambda表達(dá)式調(diào)用該方法,如下所示:

    設(shè)置<Person> rosterSetLambda =transferElements(roster,() - > {return new HashSet <>();});

    您可以使用構(gòu)造函數(shù)引用代替lambda表達(dá)式,如下所示:

    設(shè)置<Person> rosterSet = transferElements(roster,HashSet :: new);

    Java編譯器推斷您要?jiǎng)?chuàng)建HashSet包含類型元素的集合Person。或者,您可以按如下方式指定:

    設(shè)置<Person> rosterSet = transferElements(名冊(cè),HashSet <Person> :: new);

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/xasdh/p/10762717.html

    新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎(jiǎng)!定制產(chǎn)品紅包拿不停!

    總結(jié)

    以上是生活随笔為你收集整理的Java lambda expression的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。