亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java8中的lambda表達式,看這篇絕對夠

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

Lambda表達式

Lambda是簡潔的標識可傳遞匿名函數(shù)的一種方式。“互動”事件驅動下,最終面向對象編程和函數(shù)式編程結合才是趨勢。 java中,一段代碼的傳遞并不容易。因為JAVA是面向對象的語言,如果要傳遞一段代碼,必須先構建類,再生成對應的對象來傳遞所要的代碼。

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

在java8之前已經(jīng)有了多年的實驗,然后JAVA8來了。

特性

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

一、lambda表達式介紹

1.1 lambda表達式結構 

在這里插入圖片描述

1.2 常見的Lambda表達式

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

1.3 基本語法

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

1.4 類型檢查

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

1.5 類型推斷

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

當lambda只有一個參數(shù)需要推斷類型時,參數(shù)兩邊的括號可以省略

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

1.6 變量作用域

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

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

1.7 方法引用

對于已有的方法,如果希望作為lambda表達式來使用,可以直接使用方法引用

三種方法引用的情況

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

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

例如:

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

對于第三種,則相當于第一個參數(shù)成為執(zhí)行方法的對象

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

1.8 構造器引用

對于構造器引用,相當于根據(jù)構造器的方法的參數(shù),生成一個構造的對象的一個lambda表達式

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

二、在何處使用lambda表達式

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

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

不同接口的默認方法沖突問題

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

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

其他:

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

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

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

Predicate接口

方法簽名為,輸入某個對象 返回布爾結果

	/**
     * java.util.Predicate 是一個只有test方法,返回布爾值的一個函數(shù)式接口,
     * 與其類似的還有用于比較,排序的Comparator接口,其只有一個返回整數(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 ()方法簽名為,輸入某個對象 返回void

	/**
     * 常用2:Consume
     * consume接口定義了一個 名為accept的抽象方法,接收泛型 T 返回void
     * 可用來訪問T類型的對象,并且執(zhí)行某些操作。
     * 如下用其創(chuàng)建,一個foreach方法,可以實現(xiàn)對所有List的遍歷。且對每個對象執(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í)行某項操作
foreach(appleList,(Apple a)->{if (a.getColor()==null);a.setColor("garly");});
appleList.forEach((Apple a)->{if (a.getColor()==null);a.setColor("garly");});

Function接口

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

	/**
     * 常用2:Consume
     * consume接口定義了一個 名為accept的抽象方法,接收泛型 T 返回void
     * 可用來訪問T類型的對象,并且執(zhí)行某些操作。
     * 如下用其創(chuàng)建,一個foreach方法,可以實現(xiàn)對所有List的遍歷。且對每個對象執(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í)行某項操作
        foreach(appleList,(Apple a)->{if (a.getColor()==null);a.setColor("garly");});
        appleList.forEach((Apple a)->{if (a.getColor()==null);a.setColor("garly");});

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

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

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

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

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

  • DoublePredict
  • IntConsumer
  • LongBinaryOperate

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

  • ToIntFunction

2.5 復合Lambda函數(shù)

	List<Apple>apples=newArrayList<>();
	apples.add(newApple("red",11));
	apples.add(newApple("red",12));
	apples.add(newApple("green",13));
	
	/**
	*對排序lanmbda進行復復合-比較器鏈
	*1、默認逆序方法:reversed()
	*2、多級比較:thenComparing()
	*example:對apples按照顏色排序后,進行逆序,如果顏色一樣再按照重量遞增
	*/
	Comparator<Apple>comparator=Comparator.comparing(Apple::getColor).reversed().thenComparing(Apple::getWeight);
	apples.sort(comparator);
	
	
	/**
	*謂詞復合且、或、非
	*1、negate否定
	*2、and且
	*3、or或
	*example:對不是紅色的蘋果進行過濾,且收集重量大于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ù)復合
	*1、andThen將前一lambda執(zhí)行結果,作為后一表達式的參數(shù)
	*2、compose將后一表達式的結果作為前一表達式的參數(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);

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

相關文章

最新評論