最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java-lambda表達(dá)式入門看這一篇就夠了

 更新時(shí)間:2021年05月31日 10:16:34   作者:吾仄lo咚鏘  
lambda表達(dá)式最簡單的作用就是用于簡化創(chuàng)建匿名內(nèi)部類對(duì)象,Lambda表達(dá)式是一個(gè)可傳遞的代碼塊,可以在以后執(zhí)行一次或多次,下面通過本文給大家介紹Java-lambda表達(dá)式入門教程,感興趣的朋友一起看看吧

在這里插入圖片描述

概述

Lambda表達(dá)式,也可稱為閉包,是JDK8的新特性。Lambda 允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞進(jìn)方法中),可以使代碼變的更加簡潔緊湊。Lambda表達(dá)式是一個(gè)可傳遞的代碼塊,可以在以后執(zhí)行一次或多次。

名字起源是以前還沒有計(jì)算機(jī)時(shí),邏輯學(xué)家Alonzo Church想要形式化的表示能有效計(jì)算的數(shù)學(xué)函數(shù),使用了希臘字母lambda( λ \lambda λ)來標(biāo)記參數(shù),從那以后,帶參數(shù)變量的表達(dá)式就被稱為lambda表達(dá)式。

lambda表達(dá)式本質(zhì)是一個(gè)匿名函數(shù),比如以下函數(shù)

public int add(int x, int y) {
    return x + y;
}

可以轉(zhuǎn)換為:

(int x, int y) -> x + y;

語法

語法格式如下

(parameters) -> expression
或
(parameters) ->{ statements; }

其中()用來描述參數(shù)列表,{}用來描述方法體,->是lambda運(yùn)算符,讀作goes to。

可以包含顯示的return語句,如:

(String sirst,String second)->
{
	if(first.length()<second.length())return -1;
	else if(first.length()>second.length())return 1;
	else return 0;
}

可以沒有參數(shù),但()不可缺?。?br /> ()->{for(int i=0;i<10;i++)System.out.print(i);}

如果可以推導(dǎo)出參數(shù)類型,則可以忽略其類型:
Comparator<String>cmp=(first,second)->first.length()-second.length();

特別注意不能只在某些分支返回一個(gè)值,這是不合法的,如:
(int x)->{if(x>=0)return 1;}

常用示例:

ArrayList<Integer>list=new ArrayList<>();
Collections.addAll(list,1,2,3,4,5);
//遍歷
list.forEach(e->{System.out.println(e);});
//刪除指定值
list.removeIf(e->e==3);
//排序
list.sort((o1,o2)->o2-o1);
//遍歷(雙冒號(hào)操作符)
list.forEach(System.out::println);

函數(shù)式接口

Java中又很多封裝代碼塊的接口,如ActionListenerComparator等,lambda表達(dá)式與這些接口時(shí)兼容的。
對(duì)于只有一個(gè)抽象方法的接口,需要這種接口的對(duì)象時(shí),就可以提供一個(gè)lambda表達(dá)式,這種接口稱為函數(shù)式接口。

比如Arrays.sort()方法,它的第二個(gè)參數(shù)需要一個(gè)Comparator實(shí)例,而Comparator就是只有一個(gè)方法的接口,所以可以使用lambda表達(dá)式替代,可以把lambda表達(dá)式看作一個(gè)函數(shù),而不是一個(gè)對(duì)象,如:

Arrays.sort(arrays,
	(first,second)->first.length()-second.length());

lambda表達(dá)式還可以轉(zhuǎn)換為接口,比如實(shí)現(xiàn)Runnable接口:

new Thread(() -> System.out.println("記得一鍵三連")).start();
Runnable r = () -> System.out.println("(。・∀・)ノ");
r.run();

再如之前提到的removeIf()方法,它的參數(shù)就是一個(gè)Predicate接口(位于java.util.function包),這個(gè)接口專門用來傳遞lambda表達(dá)式,如刪除一個(gè)數(shù)組列表所有null值:

list.removeIf(e->e==null)

方法引用

當(dāng)在Lambda表達(dá)式中直接調(diào)用了一個(gè)方法時(shí)可以使用,其寫法為目標(biāo)引用::方法名稱。
有時(shí)候,可能已經(jīng)有現(xiàn)成的方法可以完成你想要傳遞到其他代碼的某個(gè)動(dòng)作,如遍歷打印集合:

list.forEach(e->{System.out.println(e);});

我們可以直接把現(xiàn)成的println方法傳遞給它:

list.forEach(System.out::println);

它們是等價(jià)的,是一個(gè)方法引用的寫法。
再如對(duì)字符串排序而不考慮大小寫,可以直接傳遞以下方法表達(dá)式:

Arrays.sort(strings,String::compareToIgnoreCase);

也就是說使用雙冒號(hào)操作符::來分離方法名與對(duì)象或類名:

  1. object::instanceMethod
  2. Class::staticMethod
  3. Class::instanceMethod

對(duì)于前兩種情況,方法引用等價(jià)于提供方法參數(shù)的lambda表達(dá)式,如,Math::Pow等價(jià)于(x,y)->Math.pos(x,y)。
對(duì)于第三種情況,第一個(gè)參數(shù)會(huì)成為方法的目標(biāo),如String::compareToIgnoreCase等同于(x,y)->x.compareToIgnoreCase(y)。

也可以在方法中引用this參數(shù),如this::equals等價(jià)于x->this.equals(x),同樣的,使用super也是允許的。

插播反爬信息 )博主CSDN地址:https://wzlodq.blog.csdn.net/

構(gòu)造器引用

構(gòu)造器引用與方法引用很類似,只不過方法名為new,例如Person::new是Person類構(gòu)造器的一個(gè)引用,如果有多個(gè)構(gòu)造器,編譯器會(huì)取決于上下文。比如有一個(gè)字符串列表,可以把他轉(zhuǎn)換為一個(gè)Person對(duì)象數(shù)組,為此要在各個(gè)字符串上調(diào)用構(gòu)造器。

可以用數(shù)組類型建立構(gòu)造器引用,如int[]::new是一個(gè)構(gòu)造器引用,它有一個(gè)參數(shù)即數(shù)組長度,等價(jià)于lambda表達(dá)式:x->new int[x];

在Java中無法構(gòu)造泛型類型T的數(shù)組,而數(shù)組構(gòu)造器引用就可克服這個(gè)限制。如表達(dá)式new T[n]會(huì)產(chǎn)生錯(cuò)誤,因?yàn)檫@會(huì)改為new Object[n]。設(shè)我們需要一個(gè)Person對(duì)象數(shù)組,Stream接口有一個(gè)toArray方法可以返回Object數(shù)組:

Object[] people=stream.toArray();

以上得到的是一個(gè)Object引用數(shù)組,可以把Person[]::new傳入給toArray()方法,從而得到一個(gè)Person對(duì)象數(shù)組:

Object[] people=stream.toArray(Person[]::new);

變量作用域

有時(shí)候,我們希望能夠在lambda表達(dá)式中訪問外圍方法或類中的變量,如下面例子:

public static void printTip(String text) {
	    Runnable r = () -> System.out.println(text);
	    r.run();
	}
	public static void main(String[] args) {
	    String text="一鍵三連";
	    printTip(text);
	}

現(xiàn)在來看lambda表達(dá)式中的text變量,它并不是在這個(gè)lambda表達(dá)式中定義的,實(shí)際上是printTip方法的一個(gè)參數(shù)變量。但仔細(xì)想想,lambda表達(dá)式的代碼可能會(huì)在printTip調(diào)用返回很久以后才運(yùn)行,而那時(shí)這個(gè)參數(shù)變量已經(jīng)不存在了,如何保留text變量?

首先鞏固瞎lambda表達(dá)式的理解,lmabda表達(dá)式有3個(gè)部分:一個(gè)代碼塊、變量、自由變量的值(指非參數(shù)而且不在代碼中定義的變量)。在上面的例子中,lambda表達(dá)式有一個(gè)自由變量text,表示lambda表達(dá)式的數(shù)據(jù)結(jié)構(gòu)必須存儲(chǔ)的值(這里的字符串“一鍵三連”),我們稱它被lambda表達(dá)式捕獲(captured)。

關(guān)于代碼塊和自由變量值有一個(gè)術(shù)語:閉包(closure),在Java中,lambda表達(dá)式就是閉包。

lambda表達(dá)式捕獲變量必須遵循的規(guī)則:捕獲的變量必須實(shí)際上必須是最終變量(effectively final),最終變量是指這個(gè)變量初始化之后就不會(huì)再為它賦新值,即在lambda表達(dá)式內(nèi)外都不能在修改值。

如lambda內(nèi)修改:

 public static void printTip(String text) {
        Runnable r = () -> {
            System.out.println(text);
            text="修改值會(huì)報(bào)錯(cuò)";
        };
        r.run();
    }
    public static void main(String[] args) {
        String text="一鍵三連";
        printTip(text);
    }

lambda外修改:

 public static void main(String[] args) {
        for(int i=0;i<5;i++){
            //表達(dá)式外修改變量i報(bào)錯(cuò)
            Runnable r = () -> System.out.println(i);
            r.run();
        }
    }

此外,在方法中不能有同名的局部變量,lambda表達(dá)式也是如此:

public static void main(String[] args) {
        int first=666;
        //同名會(huì)報(bào)錯(cuò)
        Comparator<String> cmp=
                (first,second)->first.length()-second.length();
    }

對(duì)于lambda表達(dá)式中使用this關(guān)鍵字時(shí),是指創(chuàng)建這個(gè)lambda表達(dá)式的方法餓this參數(shù)。

處理lambda表達(dá)式

使用lambda表達(dá)式的重點(diǎn)是延遲執(zhí)行(deferred execution)。如果要立即執(zhí)行代碼的畫完全可以直接執(zhí)行而無需放到一個(gè)lambda表達(dá)式中,之所以希望以后在執(zhí)行代碼,這有很多原因,如:

  • 在一個(gè)單獨(dú)的線程中運(yùn)行代碼
  • 多次運(yùn)行代碼
  • 在算法的適當(dāng)位置運(yùn)行代碼
  • 發(fā)生某種情況時(shí)執(zhí)行代碼
  • 只有在必要時(shí)才運(yùn)行代碼

設(shè)想要重復(fù)一個(gè)動(dòng)作n次,將這個(gè)動(dòng)作和重復(fù)次數(shù),傳遞到一個(gè)repeat方法,要接受這個(gè)lambda表達(dá)式需要選擇一個(gè)函數(shù)式接口,在這里我們可以使用Runnable接口,后面給出Java API中提供的最重要的函數(shù)式接口。

public static void repeat(int n,Runnable action){
        for(int i=0;i<n;i++)
            action.run();
    }
    public static void main(String[] args) {
        repeat(10,()-> System.out.println("一鍵三連"));
    }

函數(shù)式接口

函數(shù)式接口 參數(shù)類型 返回類型 抽象方法名 描述 其他方法
Runnable void run 作為無參數(shù)或返回值的動(dòng)作執(zhí)行
Supplier<T> T get 提供一個(gè)T類型的值
Consumer<T> T void accept 處理一個(gè)T類型的值 addThen
BiConsumer<T,U> T,U void accept 處理T和U類型的值 addThen
Function<T,R> T R apply 有一個(gè)T類型參數(shù)的函數(shù) compose,addThen,idenity
BiFunction<T,U,R> T,U R apply 有T和U類型參數(shù)的函數(shù) addThen
UnaryOperator<T> T T apply 類型T上的一元操作符 compose,addThen,identity
BinaryOperator<T> T,T T apply 類型T上的二元操作符 addThen,maxBy,minBy
PreDicate<T> T boolean test 布爾值函數(shù) add,or,negate,isEqual
BiPredicate T,U boolean test 有兩個(gè)參數(shù)的布爾值函數(shù) add,or,negate

現(xiàn)在讓這個(gè)例子更復(fù)雜一些,我們希望知道這個(gè)動(dòng)作出現(xiàn)在哪一次迭代中。為此需要選擇一個(gè)合適的函數(shù)式接口,其中要包含一個(gè)方法,這個(gè)方法有一個(gè)int參數(shù)而且返回類型為void,如下所示:

 public interface IntConsumer{
        void accept(int value);
    }
    public static void repeat(int n,IntConsumer action){
        for(int i=0;i<n;i++)
            action.accept(i);
    }
    public static void main(String[] args) {
        repeat(10,i-> System.out.println(9-i));
    }

下表列出了基本類型int、long和double的34個(gè)可能的規(guī)范,最好使用這些特殊化規(guī)范來減少自動(dòng)裝箱:

函數(shù)式接口 參數(shù)類型 返回類型 抽象方法名
BooleanSupplier none boolean getAsBoolean
P P PSupplier none p p p getAs P P P
P P PConsumer p p p void accept
Obj P P PConsumer<T> T, p p p void accept
P P PFunction<T> p p p T apply
P P PToQFunction p p p q q q applyAs Q Q Q
To P P PFunction<T> T p p p applyAs P P P
To P P PBiFunction<T,U> T,U p p p applyAs P P P
P P PUnaryOperator p p p p p p applyAs P P P
P P PBinaryOperator p p p, p p p p p p applyAs P P P
P P PPredicate p p p boolean test

p p p, q q q為int,long,double;
P P P, Q Q

以上就是Java-lambda表達(dá)式入門看這一篇就夠了的詳細(xì)內(nèi)容,更多關(guān)于Java-lambda表達(dá)式入門的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 解決創(chuàng)建springboot后啟動(dòng)報(bào)錯(cuò):Failed?to?bind?properties?under‘spring.datasource‘

    解決創(chuàng)建springboot后啟動(dòng)報(bào)錯(cuò):Failed?to?bind?properties?under‘spri

    在Spring?Boot項(xiàng)目中,application.properties和application.yml是用于配置參數(shù)的兩種文件格式,properties格式簡潔但不支持層次結(jié)構(gòu),而yml格式支持層次性,可讀性更好,在yml文件中,要注意細(xì)節(jié),比如冒號(hào)后面需要空格
    2024-10-10
  • Java中的靜態(tài)代碼塊與構(gòu)造代碼塊詳解

    Java中的靜態(tài)代碼塊與構(gòu)造代碼塊詳解

    靜態(tài)代碼塊在JVM加載類時(shí)執(zhí)行,僅執(zhí)行一次,用于初始化靜態(tài)變量或執(zhí)行一次性設(shè)置,構(gòu)造代碼塊在每次創(chuàng)建對(duì)象時(shí)執(zhí)行,用于實(shí)例變量的初始化或執(zhí)行創(chuàng)建對(duì)象時(shí)的公共邏輯,靜態(tài)代碼塊按定義順序執(zhí)行,構(gòu)造代碼塊在構(gòu)造方法前執(zhí)行
    2024-11-11
  • 淺談Java 類中各成分加載順序和內(nèi)存中的存放位置

    淺談Java 類中各成分加載順序和內(nèi)存中的存放位置

    下面小編就為大家?guī)硪黄獪\談Java 類中各成分加載順序和內(nèi)存中的存放位置。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • Java中注解@JsonFormat與@DateTimeFormat的使用

    Java中注解@JsonFormat與@DateTimeFormat的使用

    從數(shù)據(jù)庫獲取時(shí)間傳到前端進(jìn)行展示的時(shí)候,我們有時(shí)候可能無法得到一個(gè)滿意的時(shí)間格式的時(shí)間日期,本文主要介紹了Java中注解@JsonFormat與@DateTimeFormat的使用,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • Java處理科學(xué)計(jì)數(shù)法數(shù)字方式

    Java處理科學(xué)計(jì)數(shù)法數(shù)字方式

    這篇文章主要介紹了Java處理科學(xué)計(jì)數(shù)法數(shù)字方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java cookie和session會(huì)話技術(shù)介紹

    Java cookie和session會(huì)話技術(shù)介紹

    session的工作原理和cookie非常類似,在cookie中存放一個(gè)sessionID,真實(shí)的數(shù)據(jù)存放在服務(wù)器端,客戶端每次發(fā)送請(qǐng)求的時(shí)候帶上sessionID,服務(wù)端根據(jù)sessionID進(jìn)行數(shù)據(jù)的響應(yīng)
    2023-04-04
  • MyBatis詳細(xì)講解DAO代理的使用

    MyBatis詳細(xì)講解DAO代理的使用

    MyBatis允許只聲明一個(gè)dao接口,而無需寫dao實(shí)現(xiàn)類的方式實(shí)現(xiàn)數(shù)據(jù)庫操作。前提是必須保證Mapper文件中的<mapper>標(biāo)簽的namespace屬性值必須要和dao接口的類路徑一致,MyBatis容器會(huì)自動(dòng)通過動(dòng)態(tài)代理生成接口的實(shí)現(xiàn)類
    2022-04-04
  • Mybatis映射文件詳解之mapper.xml文件

    Mybatis映射文件詳解之mapper.xml文件

    本文詳細(xì)介紹了Mybatis映射文件的結(jié)構(gòu)、標(biāo)簽和使用方法,包括mapper元素、標(biāo)簽的主要屬性如id、parameterType、resultType以及動(dòng)態(tài)SQL和結(jié)果映射的使用,通過映射文件,可以將數(shù)據(jù)庫表與Java對(duì)象映射,支持查詢、插入、更新、刪除等操作,提高了SQL語句的靈活性和可重用性
    2024-09-09
  • Springboot 全局時(shí)間格式化操作

    Springboot 全局時(shí)間格式化操作

    這篇文章主要介紹了Springboot 全局時(shí)間格式化操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot參數(shù)校驗(yàn)的一些實(shí)戰(zhàn)應(yīng)用

    SpringBoot參數(shù)校驗(yàn)的一些實(shí)戰(zhàn)應(yīng)用

    這篇文章主要給大家介紹了關(guān)于SpringBoot參數(shù)校驗(yàn)的一些實(shí)戰(zhàn)應(yīng)用,包括使用內(nèi)置的參數(shù)校驗(yàn)注解、嵌套對(duì)象校驗(yàn)、分組校驗(yàn)以及自定義校驗(yàn)注解,通過這些方法,可以有效地提高系統(tǒng)的穩(wěn)定性和安全性,需要的朋友可以參考下
    2024-11-11

最新評(píng)論

分宜县| 哈密市| 老河口市| 阿克苏市| 铁力市| 外汇| 鄂温| 论坛| 名山县| 同仁县| 辉县市| 文水县| 论坛| 会东县| 淄博市| 韶山市| 廊坊市| 林周县| 三明市| 同仁县| 庆安县| 丰顺县| 读书| 诏安县| 施秉县| 托克托县| 安庆市| 洪雅县| 高碑店市| 凌海市| 抚顺市| 进贤县| 隆德县| 唐山市| 辽宁省| 孟津县| 宜宾市| 沅江市| 屯昌县| 重庆市| 民勤县|