亚洲区国产区激情区无码区,国产成人mv视频在线观看,国产A毛片AAAAAA,亚洲精品国产首次亮相在线

Java 菜鳥教程

Java 流程控制

Java 數(shù)組

Java 面向?qū)ο?I)

Java 面向?qū)ο?II)

Java 面向?qū)ο?III)

Java 異常處理

Java 列表(List)

Java Queue(隊(duì)列)

Java Map集合

Java Set集合

Java 輸入輸出(I/O)

Java Reader/Writer

Java 其他主題

Java Lambda 表達(dá)式

在本文中,我們將通過示例了解Java lambda表達(dá)式,以及l(fā)ambda表達(dá)式與函數(shù)接口、泛型函數(shù)接口和流API的使用。

lambda表達(dá)式是在Java 8中首次引入的。其主要目的是提高語言的表達(dá)能力。

但是,在學(xué)習(xí)lambda之前,我們首先需要了解功能接口。

什么是功能接口?

如果Java接口僅包含一個抽象方法,則將其稱為功能接口。僅這一種方法指定了接口的預(yù)期用途。

例如,包java.lang中的Runnable接口;是一個功能接口,因?yàn)樗唤M成一個方法,即run()。

示例1:在java中定義功能接口

import java.lang.FunctionalInterface;
@FunctionalInterface
public interface MyInterface{
    //單一抽象方法
    double getValue();
}

在上面的示例中,接口MyInterface只有一個抽象方法getValue()。因此,它是一個功能接口。

在這里,我們使用了注解@FunctionalInterface。該注解會強(qiáng)制Java編譯器指示該接口是功能接口。因此,不允許有多個抽象方法。但是,它不是強(qiáng)制性的。

在Java 7中,功能接口被視為單一抽象方法(SAM)類型。在Java 7中,SAM類型通常是通過匿名類實(shí)現(xiàn)的。

示例2:使用Java中的匿名類實(shí)現(xiàn)SAM

public class FunctionInterfaceTest {
    public static void main(String[] args) {

        //匿名類
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我剛剛實(shí)現(xiàn)了Runnable功能接口。");
            }
        }).start();
    }
}

輸出

我剛剛實(shí)現(xiàn)了Runnable功能接口。

在這里,我們可以將匿名類傳遞給方法。這有助于用Java 7編寫代碼更少的程序。但是,語法仍然很困難,需要大量的額外代碼行。

Java 8進(jìn)一步擴(kuò)展了SAM的功能。由于我們知道功能接口只有一個方法,因此在將其作為參數(shù)傳遞時,無需定義該方法的名稱。Lambda表達(dá)式使我們能夠做到這一點(diǎn)。

Lambda表達(dá)式簡介

Lambda表達(dá)式本質(zhì)上是一個匿名或未命名的方法。lambda表達(dá)式不能單獨(dú)執(zhí)行。相反,它用于實(shí)現(xiàn)功能接口定義的方法。

如何在Java中定義Lambda表達(dá)式?

這是我們?nèi)绾卧贘ava中定義lambda表達(dá)式。

(parameter list) -> lambda body

使用的新運(yùn)算符(->)被稱為箭頭運(yùn)算符或lambda運(yùn)算符。讓我們探索一些實(shí)例,

假設(shè)我們有一個這樣的方法:

double getPiValue() {
    return 3.1415;
}

我們可以使用lambda表達(dá)式編寫此方法,如下所示:

() -> 3.1415

在此,該方法沒有任何參數(shù)。因此,運(yùn)算符的左側(cè)包括一個空參數(shù)。右側(cè)是lambda主體,用于指定lambda表達(dá)式的操作。在這種情況下,它將返回值3.1415。

Lambda 主體的類型

在Java中,lambda主體有兩種類型。

1.單個表達(dá)式主體

() -> System.out.println("Lambdas are great");

這種類型的lambda主體稱為表達(dá)式主體。

2.由代碼塊組成的主體。

() -> {
    double pi = 3.1415;
    return pi;
};

這種類型的lambda體稱為塊體。塊主體允許lambda主體包含多個語句。這些語句包含在括號內(nèi),您必須在括號后添加分號。

注意:對于塊體,您應(yīng)該始終有一個return語句。但是,單個表達(dá)式主體不需要return語句。

示例3:Lambda表達(dá)式

讓我們編寫一個Java程序,該程序使用lambda表達(dá)式返回Pi的值。

如前所述,lambda表達(dá)式不是單獨(dú)執(zhí)行的。相反,它形成了由功能接口定義的抽象方法的實(shí)現(xiàn)。

因此,我們需要首先定義一個功能接口。

import java.lang.FunctionalInterface;

//這是功能接口
@FunctionalInterface
interface MyInterface{

    // 抽象方法
    double getPiValue();
}

public class Main {

    public static void main( String[] args ) {

    //聲明對MyInterface的引用
    MyInterface ref;
    
    // lambda 表達(dá)式
    ref = () -> 3.1415;
    
    System.out.println("Pi = " + ref.getPiValue());
    } 
}

輸出

Pi = 3.1415

在以上示例中,

  • 我們創(chuàng)建了一個名為MyInterface的功能接口。它包含一個名為getPiValue()的抽象方法

  • 在Main類內(nèi)部,我們聲明了對MyInterface的引用。請注意,我們可以聲明接口的引用,但不能實(shí)例化接口。那是因?yàn)椋?br/>  

    //它將拋出一個錯誤
    MyInterface ref = new myInterface();
    
    // 這是有效的
    MyInterface ref;
  • 然后,我們?yōu)橐梅峙淞艘粋€lambda表達(dá)式。

    ref = () -> 3.1415;
  • 最后,我們使用reference接口調(diào)用方法getPiValue()。

    System.out.println("Pi = " + ref.getPiValue());

帶參數(shù)的Lambda表達(dá)式

到現(xiàn)在為止,我們已經(jīng)創(chuàng)建了不帶任何參數(shù)的lambda表達(dá)式。但是,類似于方法,lambda表達(dá)式也可以具有參數(shù)。例如,

(n) -> (n%2)==0

在此,括號內(nèi)的變量n是傳遞給lambda表達(dá)式的參數(shù)。Lambda主體接受參數(shù)并檢查其是偶數(shù)還是奇數(shù)。

示例4:將lambda表達(dá)式與參數(shù)一起使用

@FunctionalInterface
interface MyInterface {

    //抽象方法
    String reverse(String n);
}

public class Main {

    public static void main( String[] args ) {

                //聲明對MyInterface的引用
                //將lambda表達(dá)式分配給引用
        MyInterface ref = (str) -> {

            String result = "";
            for (int i = str.length()-1; i >= 0 ; i--){
                result += str.charAt(i);
            }
            
            return result;
        };

        //調(diào)用接口的方法
        System.out.println("Lambda reversed = " + ref.reverse("Lambda"));
    }

}

輸出

Lambda reversed = adbmaL

泛型功能接口

到目前為止,我們已經(jīng)使用了僅接受一種類型的值的功能接口。例如,

@FunctionalInterface
interface MyInterface {
    String reverseString(String n);
}

上面的功能接口僅接受String并返回String。但是,我們可以使功能接口通用,以便接受任何數(shù)據(jù)類型。如果不熟悉泛型,請?jiān)L問Java泛型

示例5:泛型功能接口和Lambda表達(dá)式

// GenericInterface.java
@FunctionalInterface
interface GenericInterface<T> {

    // 泛型方法
    T func(T t);
}

// GenericLambda.java
public class Main {

    public static void main( String[] args ) {

                //聲明對GenericInterface的引用
                // GenericInterface對String數(shù)據(jù)進(jìn)行操作
                //為其分配一個lambda表達(dá)式
        GenericInterface<String> reverse = (str) -> {

            String result = "";
            for (int i = str.length()-1; i >= 0 ; i--)
            result += str.charAt(i);
            return result;
        };

        System.out.println("Lambda reversed = " + reverse.func("Lambda"));

                //聲明對GenericInterface的另一個引用
                // GenericInterface對整數(shù)數(shù)據(jù)進(jìn)行操作
                //為其分配一個lambda表達(dá)式
        GenericInterface<Integer> factorial = (n) -> {

            int result = 1;
            for (int i = 1; i <= n; i++)
            result = i * result;
            return result;
        };

        System.out.println("5的階乘 = " + factorial.func(5));
    }
}

輸出

Lambda reversed = adbmaL
5的階乘 = 120

在上面的示例中,我們創(chuàng)建了一個名為GenericInterface的泛型功能接口。它包含一個名為func()的泛型方法。

在類內(nèi)部:

  • GenericInterface<String> reverse - 創(chuàng)建對該接口的引用。 現(xiàn)在,該接口可以處理String類型的數(shù)據(jù)。

  • GenericInterface<Integer> factorial -創(chuàng)建對該接口的引用。 在這種情況下,該接口對Integer類型的數(shù)據(jù)進(jìn)行操作。

Lambda表達(dá)式和流API

新的java.util.stream包已添加到JDK8中,它允許java開發(fā)人員執(zhí)行搜索、過濾、映射、減少等操作,或者操作列表等集合。

例如,我們有一個數(shù)據(jù)流(在我們的示例中是一個字符串列表),其中每個字符串都是國家名稱和國家/地區(qū)的組合。 現(xiàn)在,我們可以處理此數(shù)據(jù)流,并且僅從Nepal檢索位置。

為此,我們可以結(jié)合使用Stream API和Lambda表達(dá)式在流中執(zhí)行批量操作。

示例6:演示將lambda與Stream API一起使用

import java.util.ArrayList;
import java.util.List;

public class StreamMain {

    //使用ArrayList創(chuàng)建一個列表對象
    static List<String> places = new ArrayList<>();

    //準(zhǔn)備我們的數(shù)據(jù)
    public static List getPlaces(){

        //將地點(diǎn)和國家添加到列表中
        places.add("Nepal, Kathmandu");
        places.add("Nepal, Pokhara");
        places.add("India, Delhi");
        places.add("USA, New York");
        places.add("Africa, Nigeria");

        return places;
    }

    public static void main( String[] args ) {

        List<String> myPlaces = getPlaces();
        System.out.println("Places from Nepal:");
        
        myPlaces.stream()
                .filter((p) -> p.startsWith("Nepal"))
                .map((p) -> p.toUpperCase())
                .sorted()
                .forEach((p) -> System.out.println(p));
    }

}

輸出

Places from Nepal:
NEPAL, KATHMANDU
NEPAL, POKHARA

在上面的示例中,請注意以下語句:

myPlaces.stream()
        .filter((p) -> p.startsWith("Nepal"))
        .map((p) -> p.toUpperCase())
        .sorted()
        .forEach((p) -> System.out.println(p));

在這里,我們使用的是Stream API的filter(),map()和forEach()之類的方法。 這些方法可以將lambda表達(dá)式作為輸入。

我們還可以根據(jù)上面學(xué)習(xí)的語法定義自己的表達(dá)式。如上例所示,這使我們可以大大減少代碼行。