成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java Lambda表達(dá)式

lewif / 2126人閱讀

摘要:表達(dá)式的主要作用就是代替匿名內(nèi)部類的煩瑣語法。從這點來看,表達(dá)式的代碼塊與匿名內(nèi)部類的方法體是相同的。與匿名內(nèi)部類相似的是,由于表達(dá)式訪問了局部變量,該局部變量相當(dāng)于與一個隱式的修飾,因此不允許對局部變量重新賦值。

函數(shù)式接口

函數(shù)式接口(Functional Interface)就是一個只有一個抽象方法(可以包含多個默認(rèn)方法或多個static方法)的普通接口,可以被隱式轉(zhuǎn)換為lambda表達(dá)式,可以現(xiàn)有的函數(shù)友好地支持 lambda。

函數(shù)式接口:

java.lang.Runnable

java.util.concurrent.Callable

java.security.PrivilegedAction

java.util.Comparator

java.io.FileFilter

java.nio.file.PathMatcher

java.lang.reflect.InvocationHandler

java.beans.PropertyChangeListener

java.awt.event.ActionListener

javax.swing.event.ChangeListener

java.util.function

Lambda表達(dá)式入門

匿名內(nèi)部類:

public class CommandTest2 
{
    public static void main(String[] args) 
    {
        ProcessArray pa = new ProcessArray();
        int[] target = {3, -4, 6, 4};
        //處理數(shù)組,具體處理行為取決于匿名內(nèi)部類
        pa.process(target, new Command() 
        {
            public void process(int[] target) 
            {
                int sum = 0;
                for(int tmp :target)
                {
                    sum += tmp;
                }
                System.out.println("數(shù)組元素的總和是:"+ sum);
            }
        });
    }
}

Lambda表達(dá)式:

public class CommandTest3 
{
    public static void main(String[] args) 
    {
        ProcessArray pa = new ProcessArray();
        int[] array = {3, -4, 6, 4};
        //處理數(shù)組,具體處理行為取決于匿名內(nèi)部類
        pa.process(array, (int[] target)->{
            int sum = 0;
            for(int tmp : target)
            {
                sum += tmp;
            }
            System.out.println("數(shù)組元素的總和是:"+ sum);
        });
    }
}

當(dāng)使用Lambda表達(dá)式代替匿名內(nèi)部類創(chuàng)建對象時,Lambda表達(dá)式的代碼塊將會代替實現(xiàn)抽象方法的方法體,Lambda表達(dá)式就相當(dāng)一個匿名方法。

Lambda表達(dá)式的主要作用就是代替匿名內(nèi)部類的煩瑣語法。它由三部分組成。

形參列表。形參列表允許省略形參類型。如果形參列表只有一個參數(shù),甚至連形參列表的圓括號也可以省略。

箭頭(->)。必須通過英文中畫線號和大于符號組成。

代碼塊。如果代碼塊只包含一條語句,Lambda表達(dá)式允許省略代碼塊的花括號,那么這條語句就不用用花括號表達(dá)語句結(jié)束。Lambda代碼塊只有一條return語句,甚至可以省略return關(guān)鍵字。Lambda表達(dá)式需要返回值,而它的代碼塊中僅有一條省略了return的語句,Lambda表達(dá)式會自動返回這條語句的值。

interface Eatable
{
    void test();
}

interface Flyable
{
    void fly(String weather);
}
interface Addable
{
    int add(int a, int b);
}
public class LambdaQs 
{
    //調(diào)用該方法需要Eatable對象
    public void eat(Eatable e) 
    {
        System.out.println(e);
        e.test();
    }
    //調(diào)用該方法需要Flyable對象
    public void drive(Flyable f) 
    {
        System.out.println("老司機(jī)正在開:"+f);
        f.fly("亮瞎眼");
    }
    //調(diào)用該方法需要Addable對象
    public void test(Addable add) 
    {
        System.out.println("34與59的和為:"+add.add(34, 59));
    }
    public static void main(String[] args) 
    {
        LambdaQs lq = new LambdaQs();
        //Lamba表達(dá)式的代碼塊只有一條語句,可以省略花括號
        lq.eat(()->System.out.println("蘋果很贊哦!"));
        //Lamba表達(dá)式的形參列表只有一個形參,可以省略圓括號
        lq.drive(weather ->
        {
            System.out.println("今天天氣是:"+weather);
            System.out.println("直升機(jī)飛行平穩(wěn)");
        });
        //Lambda表達(dá)式的代碼塊只有一條語句,可以省略花括號
        //代碼塊中只有一條語句,即使該表達(dá)式需要返回值,也可以省略return關(guān)鍵字
        lq.test((a, b) -> a + b);
    }
}

Lambda表達(dá)式與函數(shù)式接口

Lambda表達(dá)式的類型,也被稱為“目標(biāo)類型”,Lambda表達(dá)式的目標(biāo)類型必須是“函數(shù)式接口”。函數(shù)式接口代表只包含一個抽象方法的接口。函數(shù)式接口可以包含多個默認(rèn)方法、類方法,但只能聲明一個抽象方法

如果采用匿名內(nèi)部類語法來創(chuàng)建函數(shù)式接口的實例,則只需要實現(xiàn)一個抽象方法,在這種情況下即可采用Lambda表達(dá)式來創(chuàng)建對象,該表達(dá)式創(chuàng)建處理的對象的目標(biāo)類型就是這個函數(shù)式接口。查詢Java8的API文檔,可以發(fā)現(xiàn)大量的函數(shù)式接口,例如:Runnable、ActionListener等接口都是函數(shù)式接口

@FunctionalInterface注解,該注解通常放在接口定義前面,該注解對程序功能沒有任何作用,它用于告訴編譯器執(zhí)行更嚴(yán)格檢查——檢查該接口必須是函數(shù)式接口,否則編譯器就會報錯

Lambda表達(dá)式實現(xiàn)的是匿名方法——因此它只能實現(xiàn)特定函數(shù)式接口中的唯一方法。這意味著Lambda表達(dá)式有如下兩個限制:

Lambda表達(dá)式的目標(biāo)類型必須是明確的函數(shù)式接口

Lambda表達(dá)式只能為函數(shù)式接口創(chuàng)建對象。Lambda表達(dá)式只能實現(xiàn)一個方法,因此它只能為只有一個抽象方法的接口(函數(shù)式接口)創(chuàng)建對象

為了保證Lambda表達(dá)式的目標(biāo)類型是一個明確的函數(shù)式接口,可以有如下三種常見方式:

將Lambda表達(dá)式賦值給函數(shù)式接口類型的變量

將Lambda表達(dá)式作為函數(shù)式接口類型的參數(shù)傳給某個方法

使用函數(shù)式接口對Lambda表達(dá)式進(jìn)行強(qiáng)制類型轉(zhuǎn)換

同樣的Lambda表達(dá)式的目標(biāo)類型完全可能是變化的——唯一的要求是,Lambda表達(dá)式實現(xiàn)的匿名方法與目標(biāo)類型(函數(shù)式接口)中唯一的抽象方法有相同的形參列表。

Java8在java.util.function包下預(yù)定義了大量函數(shù)式接口,典型地包含如下4類接口。

XxxFunction:這類接口中通常包含一個apply()抽象方法,該方法對參數(shù)進(jìn)行處理、轉(zhuǎn)換(apply()方法的處理邏輯由Lambda表達(dá)式來實現(xiàn)),然后返回一個新的值。該函數(shù)式接口通常用于對指定數(shù)據(jù)進(jìn)行轉(zhuǎn)換處理。

XxxConsumer:這類接口中通常包含一個accept()抽象方法,該方法與XxxFunction接口中的apply()方法基本相似,也負(fù)責(zé)對參數(shù)進(jìn)行處理,只是該方法不會返回處理結(jié)果。

XxxxPredicate:這類接口中通常包含一個test()抽象方法,該方法通常用來對參數(shù)進(jìn)行某種判斷(test()方法的判斷邏輯由Lambda表達(dá)式來實現(xiàn)),然后返回一個boolean值。該接口通常用于判斷參數(shù)是否滿足特定條件,經(jīng)常用于進(jìn)行篩濾數(shù)據(jù)。

XxxSupplier:這類接口中通常包含一個getAsXxx()抽象方法,該方法不需要輸入?yún)?shù),該方法會按某種邏輯算法(getAsXxx()方法的邏輯算法由Lambda表達(dá)式來實現(xiàn))返回一個數(shù)據(jù)。

方法引用與構(gòu)造器引用

如果Lambda表達(dá)式的代碼塊只有一條代碼,還可以在代碼塊中使用方法引用和構(gòu)造器引用。

方法引用和構(gòu)造器引用可以讓Lambda表達(dá)式的代碼塊更加簡潔。方法引用和構(gòu)造器引用都需要使用兩個英文冒號。

種類 示例 說明 對應(yīng)的Lambda表達(dá)式
引用類方法 類名::類方法 函數(shù)式接口中被實現(xiàn)方法的全部參數(shù)傳給該類方法作為參數(shù) (a,b,...)->類名.類方法(a,b,...)
引用特定對象的實例方法 特定對象::實例方法 函數(shù)式接口中被實現(xiàn)方法的全部參數(shù)傳給該類方法作為參數(shù) (a,b,...)->特定對象.實例方法(a,b,...)
引用某類對象的實例方法 類名::實例方法 函數(shù)式接口中被實現(xiàn)方法的第一個參數(shù)作為調(diào)用者,后面的參數(shù)全部傳給該方法作為參數(shù) (a,b,...)->a.實例方法(b,...)
引用構(gòu)造器 類名::new 函數(shù)式接口中被實現(xiàn)方法的全部參數(shù)傳給該類方法作為參數(shù) (a,b,...)->new 類名(a,b,...)
引用類方法
@FunctionalInterface
interface Converter{
    Integer convert(String from);
}

該函數(shù)式接口包含一個convert()抽象方法,該方法負(fù)責(zé)將String參數(shù)轉(zhuǎn)換成Integer。下面代碼使用Lambda表達(dá)式來創(chuàng)建Converter對象。

//下面代碼使用Lambda表達(dá)式創(chuàng)建Converter對象
Converter converter1 = from -> Integer.valueOf(from);

上面Lambda表達(dá)式的代碼塊只有一條語句,因此程序省略了該代碼塊的花括號;而且由于表達(dá)式所實現(xiàn)的convert()方法需要返回值,因此Lambda表達(dá)式將會把這條代碼的值作為返回值
調(diào)用convert1對象的convert()方法將字符串轉(zhuǎn)換為整數(shù)了,例如如下代碼

Integer val = converter1.convert("99");
System.out.println(val); // 輸出整數(shù)99

上面Lambda表達(dá)式的代碼塊只有一行調(diào)用類方法的代碼,因此可以使用如下方法引用進(jìn)行替換

// 方法引用代替Lambda表達(dá)式:引用類方法。
// 函數(shù)式接口中被實現(xiàn)方法的全部參數(shù)傳給該類方法作為參數(shù)。
Converter converter1 = Integer::valueOf;

對于上面的類方法引用,也就是調(diào)用Integer類的valueOf()類方法來實現(xiàn)Converter函數(shù)式接口中唯一的抽象方法,當(dāng)調(diào)用Converter接口中唯一的抽象方法時,調(diào)用參數(shù)將會傳給Integer類的valueOf()類方法。

引用特定對象的實例方法
// 下面代碼使用Lambda表達(dá)式創(chuàng)建Converter對象
Converter converter2 = from -> "fkit.org".indexOf(from);

Integer value = converter2.convert("it");
System.out.println(value); // 輸出2
// 方法引用代替Lambda表達(dá)式:引用特定對象的實例方法。
// 函數(shù)式接口中被實現(xiàn)方法的全部參數(shù)傳給該方法作為參數(shù)。
Converter converter2 = "fkit.org"::indexOf;

對于上面的實例方法引用,也就是調(diào)用"fkit.org"對象的indexOf()實例方法來實現(xiàn)Converter函數(shù)式接口中唯一的抽象方法,當(dāng)調(diào)用Converter接口中唯一的抽象方法時,調(diào)用參數(shù)將會傳給"fkit.org"對象的indexOf()實例方法。

引用某類對象的實例方法

定義如下函數(shù)式接口

@FunctionalInterface
interface MyTest
{
    String test(String a , int b , int c);
}

使用Lambda表達(dá)式來創(chuàng)建一個MyTest對象

MyTest mt = (a , b , c) -> a.substring(b , c);
String str = mt.test("Java I Love you" , 2 , 9);
System.out.println(str); // 輸出:va I Lo
// 方法引用代替Lambda表達(dá)式:引用某類對象的實例方法。
// 函數(shù)式接口中被實現(xiàn)方法的第一個參數(shù)作為調(diào)用者,
// 后面的參數(shù)全部傳給該方法作為參數(shù)。
MyTest mt = String::substring;
引用構(gòu)造器
@FunctionalInterface
interface YourTest
{
    JFrame win(String title);
}

下面代碼使用Lambda表達(dá)式創(chuàng)建YourTest對象

YourTest yt = (String a) -> new JFrame(a);
JFrame jf = yt.win("我的窗口");
System.out.println(jf);
// 構(gòu)造器引用代替Lambda表達(dá)式。
// 函數(shù)式接口中被實現(xiàn)方法的全部參數(shù)傳給該構(gòu)造器作為參數(shù)。
YourTest yt = JFrame::new;

對于上面的構(gòu)造器引用,也就是調(diào)用某個JFrame類的構(gòu)造器來實現(xiàn)YourTest函數(shù)式接口中唯一的抽象方法,當(dāng)調(diào)用YourTest接口中的唯一的抽象方法時,調(diào)用參數(shù)將會傳給JFrame構(gòu)造器。調(diào)用YourTest對象的win()抽象方法時,實際只傳入了一個String類型的參數(shù),這個String類型的參數(shù)會被傳給JFrame構(gòu)造器——這就確定了調(diào)用JFrame類的、帶一個String參數(shù)的構(gòu)造器。

Lambda表達(dá)式與匿名內(nèi)部類的聯(lián)系和區(qū)別

Lambda表達(dá)式是匿名內(nèi)部類的一種簡化,存在如下相同點

Lambda表達(dá)式與匿名內(nèi)部類一樣,都可以直接訪問“effectively final”的局部變量,以及外部類的成員變量(包括實例變量和類變量)。

Lambda表達(dá)式創(chuàng)建的對象與匿名內(nèi)部類生成的對象一樣,都可以直接調(diào)用從接口中繼承的默認(rèn)方法。

@FunctionalInterface
interface Displayable
{
    //定義一個抽象方法和默認(rèn)方法
    void display();
    default int add(int a, int b)
    {
        return a + b;
    }
}
public class LambdaAndInner 
{
    private int age = 24;
    private static String name = "簡單點,說話的方式簡單點" ;
    public void test() 
    {
        String sing = "演員";
        Displayable dis = () -> {
            //訪問“effectively final”的局部變量
            System.out.println("sing局部變量為:"+ sing);
            //訪問外部類的實例變量和類變量
            System.out.println("外部類的age實例變量為:"+ age);
            System.out.println("外部類的name類變量為:"+ name);
        };
        dis.display();
        //調(diào)用dis對象從接口中繼承的add()方法
        System.out.println(dis.add(34, 59));
    }
    public static void main(String[] args) 
    {
        LambdaAndInner lambdaAndInner = new LambdaAndInner();
        lambdaAndInner.test();
    }
}

上面Lambda表達(dá)式創(chuàng)建了一個Display的對象,Lambda表達(dá)式的代碼塊中的三行粗體字代碼分別示范了訪問“effectively fianl”的局部變量、外部類的實例變量和類變量。從這點來看,Lambda表達(dá)式的代碼塊與匿名內(nèi)部類的方法體是相同的。
與匿名內(nèi)部類相似的是,由于Lambda表達(dá)式訪問了sing局部變量,該局部變量相當(dāng)于與一個隱式的final修飾,因此不允許對sing局部變量重新賦值。

Lambda表達(dá)式與匿名內(nèi)部類主要存在如下區(qū)別

匿名內(nèi)部類可以為任意接口創(chuàng)建實例——不管接口包含多少個抽象方法,只有匿名內(nèi)部類實現(xiàn)所有的抽象方法即可;但Lambda表達(dá)式只能為函數(shù)式接口創(chuàng)建實例。

匿名內(nèi)部類可以為抽象類甚至普通類創(chuàng)建實例;但Lambda表達(dá)式只能為函數(shù)式接口創(chuàng)建實例。

匿名內(nèi)部類實現(xiàn)的抽象方法的方法體允許調(diào)用接口中定義的默認(rèn)方法;但Lambda表達(dá)式的代碼塊不允許調(diào)用默認(rèn)方法。

使用Lambda表達(dá)式調(diào)用Arrays的類方法

Arrays類的有些方法需要Comparator、XxxOperator、XxxFunction等接口的實例,這些接口都是函數(shù)式接口,因此可以使用Lambda表達(dá)式來調(diào)用Arrays的方法

import java.util.Arrays;

import javax.management.openmbean.OpenDataException;

public class LambdaArrays 
{
    public static void main(String[] args) 
    {
        String arr1[] = new String[]{"皇家馬德里", "巴塞羅那", "巴黎圣日耳曼","尤文圖斯","切爾西"};
        Arrays.parallelSort(arr1, (o1, o2) -> o1.length() - o2.length());
        System.out.println(Arrays.toString(arr1));
        int[] arr2 = new int[]{4, 2, 1, 3, 5};
        //left代表數(shù)組中前一個索引處的元素,計算第一個元素時,left為1
        //right代表數(shù)組中當(dāng)前索引處的元素
        Arrays.parallelPrefix(arr2, (left, right) -> left * right);
        System.out.println(Arrays.toString(arr2));
        long[] arr3 = new long[5];
        //operand代表正在計算的元素索引
        Arrays.parallelSetAll(arr3, operand -> operand * 5);
        System.out.println(Arrays.toString(arr3));
    }
}

(o1, o2) -> o1.length() - o2.length():目標(biāo)類型是Comparator指定了判斷字符串大小的標(biāo)準(zhǔn):字符串越長,即可認(rèn)為該字符串越大

(left, right) -> left * right:目標(biāo)類型是IntBinaryOperator,該對象將會根據(jù)前后兩個元素來計算當(dāng)前元素的值

operand -> operand * 5::目標(biāo)類型是IntToLongFunction,該對象將會根據(jù)元素的索引來計算當(dāng)前元素的值

Lambda表達(dá)式可以讓程序更加簡潔。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66304.html

相關(guān)文章

  • 深入淺出 Java 8 Lambda 達(dá)式

    摘要:在支持一類函數(shù)的語言中,表達(dá)式的類型將是函數(shù)。匿名函數(shù)的返回類型與該主體表達(dá)式一致如果表達(dá)式的主體包含一條以上語句,則表達(dá)式必須包含在花括號中形成代碼塊。注意,使用表達(dá)式的方法不止一種。 摘要:此篇文章主要介紹 Java8 Lambda 表達(dá)式產(chǎn)生的背景和用法,以及 Lambda 表達(dá)式與匿名類的不同等。本文系 OneAPM 工程師編譯整理。 Java 是一流的面向?qū)ο笳Z言,除了部分簡...

    wdzgege 評論0 收藏0
  • Java 8 Lambda 達(dá)式詳解

    摘要:表達(dá)式簡介表達(dá)式是一個匿名函數(shù)對于而言并不很準(zhǔn)確,但這里我們不糾結(jié)這個問題。如果表達(dá)式的正文有一條以上的語句必須包含在大括號代碼塊中,且表達(dá)式的返回值類型要與匿名函數(shù)的返回類型相同。 版權(quán)聲明:本文由吳仙杰創(chuàng)作整理,轉(zhuǎn)載請注明出處:https://segmentfault.com/a/1190000009186509 1. 引言 在 Java 8 以前,若我們想要把某些功能傳遞給某些方...

    haoguo 評論0 收藏0
  • 轉(zhuǎn) | Java8初體驗(一)lambda達(dá)式語法

    摘要:初體驗下面進(jìn)入本文的正題表達(dá)式。接下來展示表達(dá)式和其好基友的配合。吐槽一下方法引用表面上看起來方法引用和構(gòu)造器引用進(jìn)一步簡化了表達(dá)式的書寫,但是個人覺得這方面沒有的下劃線語法更加通用。 感謝同事【天錦】的投稿。投稿請聯(lián)系 [email protected] 本文主要記錄自己學(xué)習(xí)Java8的歷程,方便大家一起探討和自己的備忘。因為本人也是剛剛開始學(xué)習(xí)Java8,所以文中肯定有錯誤和理解偏...

    Lucky_Boy 評論0 收藏0
  • JAVA Lambda達(dá)式

    摘要:語言是強(qiáng)類型面向?qū)ο蟮恼Z言,所以必須提供一種數(shù)據(jù)類型作為表達(dá)式的返回值類型符合中函數(shù)格式的定義符合面向?qū)ο笠?guī)則,所以最終表達(dá)式要有一個映射成對象的過程。定一個函數(shù)式接口我們在接口里定義了一個沒有參數(shù)返回值的抽象方法。 在JAVA中,Lambda 表達(dá)式(Lambda expression)是一個抽象方法的實現(xiàn)。這個抽象方法必須是在接口中聲明的,而且實現(xiàn)類只需要實現(xiàn)這一個抽象方法,我們稱...

    Cheng_Gang 評論0 收藏0
  • Java Lambda 達(dá)式(又名閉包 (Closure)/ 匿名函數(shù) ) 筆記

    摘要:表達(dá)式又名閉包匿名函數(shù)筆記根據(jù)終于在中引入了表達(dá)式。函數(shù)式接口要介紹中表達(dá)式的實現(xiàn),需要知道什么是函數(shù)式接口。但同樣需要保證外部的自由變量不能在表達(dá)式中被改變。 Java Lambda 表達(dá)式(又名閉包 (Closure)/ 匿名函數(shù) ) 筆記 根據(jù) JSR 335, Java 終于在 Java 8 中引入了 Lambda 表達(dá)式。也稱之為閉包或者匿名函數(shù)。 showImg(https...

    fou7 評論0 收藏0

發(fā)表評論

0條評論

lewif

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<