国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

詳解 Java 中的 Lambda

開發(fā) 后端
如果你想給一個 Java 變量賦一段“代碼”,該怎么辦呢?在 Java 8 之前,這是不可能的。但在 Java 8 出現(xiàn)后,可以使用 Lambda 特性來做到這一點。

什么是 Lambda

我們知道,對于一個 Java 變量,我們可以給它賦一個“值”,然后可以用它做一些操作。

Integer a = 1;
String s = "Hello";
System.out.println(s + a);

如果你想給一個 Java 變量賦一段“代碼”,該怎么辦呢?例如,我想把右邊的代碼塊賦給一個名為 codeBlock 的 Java 變量。

在 Java 8 之前,這是不可能的。但在 Java 8 出現(xiàn)后,可以使用 Lambda 特性來做到這一點。

以下就是最直觀的寫法:

實際上是不允許這樣寫的會編譯失敗,這里只是為了讓大家方便理解

codeBlock = public void doSomething(String s) {
    System.out.println(s);
}

這種寫法不是很簡潔。我們可以去掉一些無用的聲明對代碼進行簡化。

codeBlock = public void doSomething(String s) {
   System.out.println(s);
}
// 這里的 public 是多余的,因為在這個上下文中不需要訪問修飾符。
codeBlock = void doSomething(String s) {
   System.out.println(s);
}
// 函數(shù)名 doSomething 也是多余的,因為已經(jīng)將函數(shù)體賦值給了 codeBlock。
codeBlock = void (String s) {
   System.out.println(s);
}
// 編譯器可以自行推斷返回類型,這里不需要顯式地寫出 void。
codeBlock = (String s) {
   System.out.println(s);
}
// 編譯器可以自行推斷輸入?yún)?shù)類型,這里不需要顯式地寫出 String 類型。
codeBlock = (s) -> System.out.println(s);

這樣,我們就將一段“代碼”賦給了一個變量。而“這段代碼”,或者說“賦給變量的這個函數(shù)”,就是一個 Lambda 表達(dá)式。

但這里還有一個問題,即變量 codeBlock 應(yīng)該是什么類型呢?在 Java 8 中,所有 Lambda 類型都是一個接口,而 Lambda 表達(dá)式本身,也就是“這段代碼”,需要是這個接口的一個實現(xiàn)。在我看來,這是理解 Lambda 的關(guān)鍵。簡而言之,Lambda 表達(dá)式本身就是一個接口的實現(xiàn)。直接這么說可能還是有點讓人困惑,所以我們繼續(xù)舉例。我們給上面的 codeBlock 添加一個類型:

codeBlock = (s)->System.out.println(s);

interface LambdaInterface {
    public void doSomething(String s);
}

這種只有一個函數(shù)需要實現(xiàn)的接口稱為“函數(shù)式接口”。為了防止后來的人給這個接口添加接口函數(shù),導(dǎo)致有多個接口函數(shù)需要實現(xiàn)而變成“非函數(shù)式接口”,我們可以給這個接口添加一個聲明@FunctionalInterface,這樣其他人就不能給它添加新函數(shù)了。

@FunctionalInterface
interface LambdaInterface {
    public void doSomething(String s);
}

這樣,我們就得到了一個完整的 Lambda 表達(dá)式聲明。

LambdaInterface codeBlock =(s)System.out.println(s);

Lambda 表達(dá)式的作用是什么

最直觀的作用就是使代碼極其簡潔。我們可以比較一下 Lambda 表達(dá)式和傳統(tǒng) Java 對同一接口的實現(xiàn):

interface LambdaInterface {
public void doSomething(String s);
}

// Java 8
LambdaInterface codeBlock = (s) -> System.out.println(s);

// Java 7
publicclass LambdaInterfaceImpl implements LambdaInterface {
@Override
public void doSomething(String s) {
   System.out.println(s);
 }
}

這兩種寫法本質(zhì)上是等價的。但顯然,Java 8 中的寫法更優(yōu)雅簡潔。而且,由于 Lambda 可以直接賦給變量,我們可以直接將 Lambda 作為參數(shù)傳遞給函數(shù),而 java7 必須有明確的接口實現(xiàn)和初始化定義:

// 定義了一個靜態(tài)方法 useLambda,它接受一個 LambdaInterface 類型的參數(shù)和一個 String 類型的參數(shù)。
public static void useLambda(LambdaInterface lambdaInterface, String s) {
    lambdaInterface.doSomething(s);
}

// Java 8
// 直接使用 Lambda 表達(dá)式調(diào)用 useLambda 方法。
   useLambda(s -> System.out.println(s), "Hello");
// Java 7
// 定義了一個 LambdaInterface 接口和一個實現(xiàn)該接口的 LambdaInterfaceImpl 類。
   interface LambdaInterface {
    public void doSomething(String s);
}

publicclass LambdaInterfaceImpl implements LambdaInterface {
    @Override
    public void doSomething(String s) {
        System.out.println(s);
    }
}
// 實例化 LambdaInterfaceImpl 類,并將實例傳遞給 useLambda 方法。
LambdaInterface myLambdaInterface = new LambdaInterfaceImpl();
useLambda(myLambdaInterface, "Hello");

在某些情況下,這個接口實現(xiàn)只需要使用一次。Java 7 要求你定義一個接口然后實現(xiàn)它。相比之下,Java 8 的 Lambda 看起來干凈得多。Lambda 結(jié)合了函數(shù)式接口庫、forEach、stream()、方法引用等新特性,使代碼更加簡潔!我們直接看例子。

@Getter
@AllArgsConstructor
public static class Student {
    private String name;
    private Integer age;
}

List<Student> students = Arrays.asList(
        new Student("Bob", 18),
        new Student("Ted", 17),
        new Student("Zeka", 18)
);

現(xiàn)在你需要打印出 students 中所有 18 歲學(xué)生的名字。

原始的 Lambda 寫法:定義兩個函數(shù)式接口,定義一個靜態(tài)函數(shù),調(diào)用靜態(tài)函數(shù)并給參數(shù)賦值 Lambda 表達(dá)式。

@FunctionalInterface
interface AgeMatcher {
    boolean match(Student student);
}

@FunctionalInterface
interface Executor {
    boolean execute(Student student);
}

public static void matchAndExecute(List<Student> students, AgeMatcher matcher, Executor executor) {
    for (Student student : students) {
        if (matcher.match(student)) {
            executor.execute(student);
        }
    }
}

public static void main(String[] args) {
    List<Student> students = Arrays.asList(
            new Student("Bob", 18),
            new Student("Ted", 17),
            new Student("zeka", 18)
    );
    matchAndExecute(students,
            s -> s.getAge() == 18,
            s -> System.out.println(s.getName())
    );
}

這段代碼實際上已經(jīng)比較簡潔了,但我們還能更簡潔嗎?當(dāng)然可以,Java 8 中有一個函數(shù)式接口包,它定義了大量可能用到的函數(shù)式接口(java.util.function (Java Platform SE 8))。

因此,我們根本不需要在這里定義 AgeMatcher 和 Executor 這兩個函數(shù)式接口。我們可以直接使用 Java 8 函數(shù)式接口包中的 Predicate(T) 和 Consumer(T),因為它們的一對接口定義實際上與 AgeMatcher/Executor 相同。

第一步簡化:利用函數(shù)式接口

public static void matchAndExecute(List<Student> students, Predicate<Student> predicate, Consumer<Student> consumer) {
    for (Student student : students) {
        if (predicate.test(student)) {
            consumer.accept(student);
        }
    }
}

matchAndExecute 中的 forEach 循環(huán)實際上很煩人。這里可以使用 Iterable 自帶的 forEach 代替。forEach 本身可以接受一個 Consumer(T) 參數(shù)。

第二步簡化:用 Iterable.forEach 代替 forEach 循環(huán):

public static void matchAndExecute(List<Student> students, Predicate<Student> predicate, Consumer<Student> consumer) {
    students.forEach(s -> {
        if (predicate.test(s)) {
            consumer.accept(s);
        }
    });
}

由于 matchAndExecute 實際上只是對 List 的一個操作,這里我們可以去掉 matchAndExecute,直接使用 stream() 特性來完成它。stream() 的幾個方法接受 Predicate(T) 和 Consumer(T) 等參數(shù)(java.util.stream (Java Platform SE 8))。一旦你理解了上面的內(nèi)容,stream() 就很容易理解,不需要進一步解釋。

第三步簡化:用 stream() 代替靜態(tài)函數(shù):

students.stream()
       .filter(s -> s.getAge() == 18)
       .forEach(s -> System.out.println(s.getName()));

與最初的 Lambda 寫法相比代碼量已經(jīng)減少了非常多。但如果我們要求改為打印學(xué)生的所有信息,并且s -> System.out.println(s);那么我們可以使用方法引用來繼續(xù)簡化。所謂方法引用,就是用已經(jīng)編寫好的其他 Object/Class 的方法來代替 Lambda 表達(dá)式。格式如下:

第四步簡化:可以在 forEach 中使用方法引用代替 Lambda 表達(dá)式:

students.stream()
       .filter(s -> s.getAge() == 18)
       .map(Student::getName)
       .forEach(System.out::println);

這基本上是我能寫出的最簡潔的版本了。

關(guān)于 Java 中的 Lambda 還有一些需要討論和學(xué)習(xí)的地方。例如,如何利用 Lambda 的特性進行并行處理等。總之,我只是給你一個大致的介紹,讓你有個概念。網(wǎng)上有很多關(guān)于 Lambda 的相關(guān)教程,多讀多練,隨著時間的推移肯定能夠掌握它。

責(zé)任編輯:趙寧寧 來源: 程序猿技術(shù)充電站
相關(guān)推薦

2024-03-12 08:23:54

JavaLambda函數(shù)式編程

2009-07-01 09:56:10

C#3.0

2019-10-10 17:53:36

大數(shù)據(jù)平臺架構(gòu)LambdaKappa

2021-01-21 05:46:22

JavaLambda開發(fā)

2023-05-31 13:32:08

Javalambda函數(shù)

2009-06-22 10:34:43

Boost庫lambda

2009-09-14 13:57:20

C# Lambda表達(dá)Lambda表達(dá)式

2020-09-26 07:19:46

Java

2016-09-18 16:58:09

JavaProperties

2012-07-18 09:45:32

Java 8ScalaLambda

2013-01-05 02:19:50

JavaLambda表達(dá)式JVM

2020-03-29 20:38:35

PythonLambda語言

2023-10-10 10:43:19

JavaJDK1.8

2009-11-12 10:55:17

Lambda表達(dá)式

2009-06-30 15:18:10

StringBuildJava

2025-02-05 12:22:21

2009-06-25 15:20:28

CollectionMap

2012-06-26 10:03:58

JavaJava 8lambda

2022-06-27 08:36:08

PythonLambda

2009-07-09 09:51:07

Lambda表達(dá)式C#
點贊
收藏

51CTO技術(shù)棧公眾號

欧美一级在线看| 99精品视频在线免费播放| 欧美福利专区| 欧美噜噜久久久xxx| 9lporm自拍视频区在线| 欧美在线观看一区| 在线免费观看黄色片| 国产精品国产精品国产专区不片| 国产一级大片免费看| 美女网站久久| 九色91国产| 激情一区二区| 国产精品区一区| 狠久久av成人天堂| 亚洲一区二区三区视频播放| 成人激情开心网| 国产欧美婷婷中文| 天天做天天爱天天综合网| 成人黄色午夜影院| 欧美在线亚洲| 国产精品一区二区三区不卡| 影音先锋久久资源网| 久久视频在线观看中文字幕| 亚洲美女色禁图| 色视频一区二区三区| 精品在线亚洲视频| 国产av人人夜夜澡人人爽麻豆 | 色天天综合狠狠色| 全球最大av网站久久| 少妇精69xxtheporn| 日韩中文字幕在线一区| 欧美最猛黑人xxxx黑人猛叫黄| 九色精品国产蝌蚪| 97人摸人人澡人人人超一碰| 99在线精品视频在线观看| 日韩精品久久久毛片一区二区| 国产一区啦啦啦在线观看| 缅甸午夜性猛交xxxx| 国产精品午夜免费| 免费资源在线观看| 日韩精品一区二区三区在线| 日韩在线短视频| 91精品国产乱码久久久久久蜜臀 | 激情综合在线观看| 国产欧美日韩综合| 日本福利小视频| 欧美日韩免费在线视频| 91福利国产在线观看菠萝蜜| 亚洲免费一级电影| 欧美日本三级| 在线成人一区| 一区二区欧美在线| 欧美不卡高清一区二区三区| 欧美一级高清免费播放| 黄色网址视频在线观看| 日韩国产欧美区| 中文字幕一区二区三区四区久久 | 中文字幕日本在线| 伊人男人综合视频网| 日韩mv欧美mv国产网站| 久久精彩视频| 国产日本欧洲亚洲| 日韩美女网站| 日韩最新在线视频| 一区二区三区中文| 国产精品成人久久电影| 亚洲国产人成综合网站| 电影在线观看一区| 4444欧美成人kkkk| 久久97超碰色| 蜜桃tv在线播放| 亚洲免费精彩视频| 日韩黄色大片网站| 人妻激情另类乱人伦人妻| 亚洲成人自拍偷拍| 高清欧美日韩| 你懂的网址一区二区三区| 中文字幕一区二区三区色视频| 久久电影网站| 亚洲一区中文字幕| 久久久亚洲综合| 精品一性一色一乱农村| 欧美肥婆姓交大片| 日韩欧美一级片| 精品久久ai电影| 91在线国产观看| jizz在线观看| 97人人模人人爽人人喊中文字| 久久久久99| 特黄aaaaaaaaa毛片免费视频| 亚洲美女激情视频| 国内精品美女在线观看| 日本激情视频在线| 亚洲色图激情小说| 亚洲深夜激情| 日韩黄色网址| 午夜精品久久久久久久白皮肤| 蜜臀av一区二区在线观看| 在线看黄网站| 91精品国产91久久久久| 波多野结衣一区二区三区| 手机av免费在线| 国产日韩精品推荐| 欧美性xxxxxxxxx| 精品在线手机视频| 免费男女羞羞的视频网站中文版| 欧美一级在线观看| 亚洲一区影音先锋| 免费在线观看亚洲视频| 亚洲看片一区| 毛片网站大全| 国内成人精品一区| 97精品超碰一区二区三区| free性护士videos欧美| 久久久久久九九九九| 欧美日韩在线观看视频| 日韩av字幕| 草裙成人精品一区二区三区| 欧美成人小视频| thepron国产精品| 亚洲美女av在线| 91黄视频在线| www一区二区三区| 日韩精品网站| 亚洲电影成人| 成人动漫av在线| 99久久免费精品| 免费成人av在线| 91精品成人| 99精品女人在线观看免费视频 | 婷婷综合五月| 韩国精品视频在线观看 | 国产一级做a爰片久久| 日本最新高清不卡中文字幕| 欧美一级精品大片| 欧美电影一区二区| 欧美精品一区视频| 成人性视频网站| 国产理论电影在线| 自拍网站在线观看| 99久热这里只有精品视频免费观看| 欧美日韩直播| 香港久久久电影| 日韩一级毛片| 日本成人伦理电影| 久久.com| www.av片| 亚洲欧洲日夜超级视频| 欧美日韩一区二区三区在线视频 | 在线影院av| 激情视频免费观看在线| 潘金莲一级淫片aaaaa免费看| 噜噜噜久久亚洲精品国产品麻豆| 国产精品成人播放| 美日韩精品视频免费看| 久久91精品国产| 一区二区三区欧美成人| 亚洲精品自在在线观看| 中文字幕无码精品亚洲35| 日本二区视频| 电影在线观看一区二区| 在线免费av观看| 国产视频一区二| 中文字幕av亚洲精品一部二部| 视频一区中文字幕国产| 亚洲国产精品人人做人人爽| 久久一二三国产| 精品久久久久久国产91| 亚洲欧美日韩一区二区三区在线观看| 成人免费观看男女羞羞视频| 欧美国产成人精品| 天天综合天天做天天综合| 欧美日韩一区久久| 色综合伊人色综合网站| 欧美成年人视频网站| 欧美精品中文字幕一区| 欧美日韩看看2015永久免费| 久久av超碰| 成人av片在线观看| 亚洲国产综合91精品麻豆| 欧美美女网站色| 麻豆一区二区在线观看| 97中文在线| 国产真实生活伦对白| 自由色视频.| 国产一区二区主播在线| 欧美精品1区| 久久久久国产免费免费| 日韩精品一区二区三区中文精品| 色av中文字幕一区| 中文字幕日韩免费视频| 91九色偷拍| 91美女在线免费观看| 欧美电影网址| 国产一区国产二区国产三区| 亚洲色图插插| 黄色日韩在线| 亚洲大尺度视频在线观看| 国产亚洲精品美女久久久| 国内精品一区二区三区四区|