欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java8中的lambda表達(dá)式,看這篇絕對(duì)夠

 更新時(shí)間:2022年04月06日 16:41:27   作者:栗子葉  
這篇文章主要介紹了java8中的lambda表達(dá)式,看這篇絕對(duì)夠!具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Lambda表達(dá)式

Lambda是簡(jiǎn)潔的標(biāo)識(shí)可傳遞匿名函數(shù)的一種方式。“互動(dòng)”事件驅(qū)動(dòng)下,最終面向?qū)ο缶幊毯秃瘮?shù)式編程結(jié)合才是趨勢(shì)。 java中,一段代碼的傳遞并不容易。因?yàn)镴AVA是面向?qū)ο蟮恼Z(yǔ)言,如果要傳遞一段代碼,必須先構(gòu)建類,再生成對(duì)應(yīng)的對(duì)象來(lái)傳遞所要的代碼。

在之前,JAVA的設(shè)計(jì)者都抗拒加入這一特性,雖然JAVA現(xiàn)有的特性也能通過(guò)類和對(duì)象實(shí)現(xiàn)類似的API但是這樣復(fù)雜且不易于使用。在后期,問(wèn)題早已不是JAVA是不是要變成一門使用函數(shù)式編程的語(yǔ)言,而是如何實(shí)現(xiàn)這種改變。

在java8之前已經(jīng)有了多年的實(shí)驗(yàn),然后JAVA8來(lái)了。

特性

  • 匿名:lambda表達(dá)式不像面向?qū)ο蟮姆椒ㄒ粯?,有確定的名稱。
  • 函數(shù):雖然lambda不是對(duì)象的方法,屬于某個(gè)特定的類。但是lambda表達(dá)式一樣的有參數(shù)列表、函數(shù)主體 返回類型和異常聲明
  • 傳遞:lambda表達(dá)式可以作為參數(shù)傳遞
  • 簡(jiǎn)潔:無(wú)需像匿名類一樣有固定模板的代碼,lambda寫得少而想得多
  • JAVA8中 可以為接口增加靜態(tài)方法、可以為類增加默認(rèn)方法

一、lambda表達(dá)式介紹

1.1 lambda表達(dá)式結(jié)構(gòu) 

在這里插入圖片描述

1.2 常見(jiàn)的Lambda表達(dá)式

//1、單個(gè)參數(shù)
(String s)->s.length()
//2、單個(gè)對(duì)象
(Apple a)->a.getWeight()>150
//3、多參數(shù),多語(yǔ)句
(int a,int b)->{
	System.out.println(a);
	System.out.println(b);
}
//4、空參數(shù),返回int值42
()->42
//5、多對(duì)象參數(shù)
(Applea1,Applea2)->a1.getWeight().compareTo(a2.getWeight())

1.3 基本語(yǔ)法

  • (參數(shù)…)-> 表達(dá)式 隱式返回表達(dá)式結(jié)果
  • (參數(shù)…)->{執(zhí)行語(yǔ)句} 可用return語(yǔ)句 顯示返回執(zhí)行結(jié)果
  • 函數(shù)式接口不允許拋出受檢異常
  • 注意:當(dāng)參數(shù)只有一個(gè)時(shí),也可以去掉參數(shù)的括號(hào)。原因是java編譯器的自動(dòng)類型推斷

1.4 類型檢查

  • Lambda的類型由上下文推斷而來(lái)
  • 同樣的lambda表達(dá)式,不同的函數(shù)式接口,只要方法的簽名一致,同樣的表達(dá)式可以用于不同的函數(shù)是接口。
  • 只有函數(shù)式接口的實(shí)現(xiàn),能承載lambda表達(dá)式
  • Objecto=()-{System.out.print("HellowWorld")}這是不合法的 因?yàn)镺bject不是一個(gè)函數(shù)式接口

1.5 類型推斷

Lambda表達(dá)式可以省略參數(shù)的類型,java編譯器能自動(dòng)推斷

當(dāng)lambda只有一個(gè)參數(shù)需要推斷類型時(shí),參數(shù)兩邊的括號(hào)可以省略

List<Apple> c=filter(inventory,a->"green".equals(a.getColor()));
Comparator<Apple> c=(a1,a2)->a1.getWeight.compareTo(a2.getWeight());

1.6 變量作用域

JAVA8之前 內(nèi)部類只允許訪問(wèn)final修飾的變量,現(xiàn)在使用lambda表達(dá)式,一個(gè)內(nèi)部類可以訪問(wèn)任何有效的final局部變量-任何值不會(huì)發(fā)生變化的變量

  • java限制了 lambda表達(dá)式訪問(wèn)的自由變量,值是不可更改的,因?yàn)檫@會(huì)導(dǎo)致出現(xiàn)無(wú)法預(yù)料的并發(fā)問(wèn)題。
  • java編譯器的限制是有限的,只對(duì)局部變量有效,如果使用靜態(tài)變量,或者示例變量,編譯器不會(huì)提示任何錯(cuò)誤。這樣仍然是不安全的。
  • 可以用數(shù)組 int[] counter =new int[1]; button.setOnAaction(event->counter[0]++); 任然可以讓lambda對(duì)局部變量進(jìn)行重新賦值。
  • lambda表達(dá)式的方法體,與被嵌套的代碼塊具有同樣的作用域,所有適用同樣的命名沖突和變量屏蔽規(guī)則。

1.7 方法引用

對(duì)于已有的方法,如果希望作為lambda表達(dá)式來(lái)使用,可以直接使用方法引用

三種方法引用的情況

  • 對(duì)象::實(shí)例方法
  • 類::靜態(tài)方法
  • 類::實(shí)例方法

在第一種和第二種方法引用種,方法的引用等于提供方法參數(shù)的lambda表達(dá)式

例如:

  • System.out::println() 等同于 System.out.print(x)
  • Math::pow 等同于 (x,y)->Math.pow(x,y)

對(duì)于第三種,則相當(dāng)于第一個(gè)參數(shù)成為執(zhí)行方法的對(duì)象

例如:String::compareToIngnoreCase 等同于(x,y) x.compareIngoreCase(Y);

1.8 構(gòu)造器引用

對(duì)于構(gòu)造器引用,相當(dāng)于根據(jù)構(gòu)造器的方法的參數(shù),生成一個(gè)構(gòu)造的對(duì)象的一個(gè)lambda表達(dá)式

例如:StringBuilder::new 可以表示為 (Stiring s)->new StringBuilder(s); 具體引用哪個(gè)構(gòu)造器,編譯器會(huì)根據(jù)上下文推斷使用符合參數(shù)的構(gòu)造器。

二、在何處使用lambda表達(dá)式

2.1 函數(shù)式接口介紹

總結(jié):就是只定義了一個(gè)抽象方法的接口,即使有一堆的default方法(default方法是為了增強(qiáng)某些API但避免現(xiàn)有大范圍改動(dòng)所有API所以推出了默認(rèn)方法)

不同接口的默認(rèn)方法沖突問(wèn)題

如果實(shí)現(xiàn)的接口已有一個(gè)默認(rèn)方法,但是另一個(gè)父類或者接口也有同樣的默認(rèn)方法。

  • 如果是父類和接口默認(rèn)方法一致,那么直接使用父類的方法實(shí)現(xiàn),忽略接口中的默認(rèn)方法(類優(yōu)先規(guī)則,如果嘗試重寫默認(rèn)方法toString 那么永遠(yuǎn)都不會(huì)優(yōu)于Object的toString)
  • 如果一個(gè)父接口提供了一個(gè)默認(rèn)方法,另一個(gè)接口也提供了同名稱和參數(shù)的方法(不論是否默認(rèn)方法)那么都必須覆蓋改方法。

其他:

接口中重寫Object類的方法,例如 Comparator 一般是為了關(guān)聯(lián)javadoc的注釋。

2.2 常見(jiàn)的函數(shù)式接口

介紹:函數(shù)式接口的抽象方法的簽名,基本就是lambda表達(dá)式的簽名,這種抽象方法稱為 函數(shù)描述符 

Predicate接口

方法簽名為,輸入某個(gè)對(duì)象 返回布爾結(jié)果

	/**
     * java.util.Predicate 是一個(gè)只有test方法,返回布爾值的一個(gè)函數(shù)式接口,
     * 與其類似的還有用于比較,排序的Comparator接口,其只有一個(gè)返回整數(shù)的比較接口
     * @param list
     * @param p
     * @param <T>
     * @return
     */
    public static <T> List<T> filter(List<T> list, Predicate<T> p){
        List<T> result=new ArrayList<>();
        for (T t : list) {
            if (p.test(t))
                result.add(t);
        }
        return result;
    }
    public static void main(String[] args) {
        //Predicate函數(shù)式接口示例
        List<Apple> appleList=new ArrayList<>();
        List<Apple> resulAppleList=filter(appleList,(Apple a)->a.getColor().equals("red"));
    }

Counsumer接口

Accept ()方法簽名為,輸入某個(gè)對(duì)象 返回void

	/**
     * 常用2:Consume
     * consume接口定義了一個(gè) 名為accept的抽象方法,接收泛型 T 返回void
     * 可用來(lái)訪問(wèn)T類型的對(duì)象,并且執(zhí)行某些操作。
     * 如下用其創(chuàng)建,一個(gè)foreach方法,可以實(shí)現(xiàn)對(duì)所有List的遍歷。且對(duì)每個(gè)對(duì)象執(zhí)行consume定義的操作。
     * 該foreach方法,java8之后成了List接口的default方法。
     * @param list
     * @param <T>
     */
    public static <T> void foreach(List<T> list, Consumer<T> consumer){
        for (T t : list) {
            consumer.accept(t);
        }
    }
	
	
 //Consume函數(shù)式接口示例,遍歷列表執(zhí)行某項(xiàng)操作
foreach(appleList,(Apple a)->{if (a.getColor()==null);a.setColor("garly");});
appleList.forEach((Apple a)->{if (a.getColor()==null);a.setColor("garly");});

Function接口

Apply() 方法簽名:輸入某個(gè)對(duì)象、返回某個(gè)對(duì)象

	/**
     * 常用2:Consume
     * consume接口定義了一個(gè) 名為accept的抽象方法,接收泛型 T 返回void
     * 可用來(lái)訪問(wèn)T類型的對(duì)象,并且執(zhí)行某些操作。
     * 如下用其創(chuàng)建,一個(gè)foreach方法,可以實(shí)現(xiàn)對(duì)所有List的遍歷。且對(duì)每個(gè)對(duì)象執(zhí)行consume定義的操作。
     * 該foreach方法,java8之后成了List接口的default方法。
     * @param list
     * @param <T>
     */
    public static <T> void foreach(List<T> list, Consumer<T> consumer){
        for (T t : list) {
            consumer.accept(t);
        }
    }
	
	
		//Consume函數(shù)式接口示例,遍歷列表執(zhí)行某項(xiàng)操作
        foreach(appleList,(Apple a)->{if (a.getColor()==null);a.setColor("garly");});
        appleList.forEach((Apple a)->{if (a.getColor()==null);a.setColor("garly");});

2.3 常見(jiàn)的Lambda和已有的實(shí)現(xiàn)

案例Lambda例子對(duì)應(yīng)的函數(shù)式接口
布爾表達(dá)式(List list) ->list.isEmpty()Predicate<List
創(chuàng)建對(duì)象()->new APPle()Supplier
消費(fèi)一個(gè)對(duì)象(Apple a->{sout(a.getColor());}Consumer
從一個(gè)對(duì)象中提取(Apple a)>a.geWeight()Function 或者其特殊化的 ToIntFunction
合并兩個(gè)值(int a,int b)->a+bIntBinaryOperator
比較兩個(gè)對(duì)象(Apple a1,Apple a2)->a1.getWeight().compareTo(a2.getWeight())Comparator BigFunction<Apple,Apple,Integer> ToIntBigFunction<Apple,Apple>

2.4 針對(duì)裝箱拆箱的優(yōu)化

java的基本類型和引用類型之間,會(huì)自動(dòng)的進(jìn)行拆箱裝箱,但是本質(zhì)是吧原始類型包裹起來(lái)再保存在堆內(nèi)存,所以裝箱后需要更多內(nèi)存。java位基本的類型定義了特有的函數(shù)式接口,一般只需要加上原始類型的前綴即可

輸入基本類型的函數(shù)式接口:

  • DoublePredict
  • IntConsumer
  • LongBinaryOperate

輸出基本類型的函數(shù)式接口:

  • ToIntFunction

2.5 復(fù)合Lambda函數(shù)

	List<Apple>apples=newArrayList<>();
	apples.add(newApple("red",11));
	apples.add(newApple("red",12));
	apples.add(newApple("green",13));
	
	/**
	*對(duì)排序lanmbda進(jìn)行復(fù)復(fù)合-比較器鏈
	*1、默認(rèn)逆序方法:reversed()
	*2、多級(jí)比較:thenComparing()
	*example:對(duì)apples按照顏色排序后,進(jìn)行逆序,如果顏色一樣再按照重量遞增
	*/
	Comparator<Apple>comparator=Comparator.comparing(Apple::getColor).reversed().thenComparing(Apple::getWeight);
	apples.sort(comparator);
	
	
	/**
	*謂詞復(fù)合且、或、非
	*1、negate否定
	*2、and且
	*3、or或
	*example:對(duì)不是紅色的蘋果進(jìn)行過(guò)濾,且收集重量大于100的蘋果
	*/
	Predicate<Apple>redApplePredicate=a->a.getColor().equals("red");
	Predicate<Apple>notRedApple=redApplePredicate.negate();
	List<Apple>notRedAppleList=apples.stream().filter(notRedApple.and(apple->apple.getWeight()>100)).collect(Collectors.toList());
	
	
	/**
	*函數(shù)復(fù)合
	*1、andThen將前一lambda執(zhí)行結(jié)果,作為后一表達(dá)式的參數(shù)
	*2、compose將后一表達(dá)式的結(jié)果作為前一表達(dá)式的參數(shù)
	*example;complexReult=g(f(x))例如g(f(1))step1:1+1=2step2:(1+1)*2+""
	*/
	Function<Integer,Integer>f=x->x+1;
	Function<Integer,String>g=x->x*2+"";
	Function<Integer,String>complexResult1=f.andThen(g);

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。 

相關(guān)文章

最新評(píng)論