日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Lambda表达式Java教程

發(fā)布時(shí)間:2023/12/3 java 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lambda表达式Java教程 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在本文中,我們提供了全面的Lambda Expressions Java教程。

1. Lambda Expressions Java教程–簡(jiǎn)介

Lambda表達(dá)式被認(rèn)為是Java 8中引入的最好的功能之一。Lambda表達(dá)式被認(rèn)為是Java進(jìn)入函數(shù)式編程世界的第一步 。 可以將其視為無(wú)需類即可創(chuàng)建的函數(shù)。 它也可以像參數(shù)一樣傳遞,并且可以在需要時(shí)和根據(jù)需要執(zhí)行。 Java Lambda表達(dá)式是匿名函數(shù)的簡(jiǎn)潔表示,可以將其傳遞。 具有單個(gè)功能的匿名類通過(guò)額外的語(yǔ)法呈現(xiàn)出笨拙的外觀。 這些表述旨在消除這種混亂。

如前所述,Java Lambda表達(dá)式是無(wú)名函數(shù) ,可以作為常量值進(jìn)行傳遞。 這意味著它們可以存在于可能存在任何其他常數(shù)值的任何位置,但是通常作為參數(shù)寫(xiě)入某些其他函數(shù)。 考慮一個(gè)典型的例子,我們可以將比較函數(shù)傳遞給泛型排序函數(shù),而不是麻煩地定義一個(gè)整個(gè)過(guò)程(并引起詞法不連續(xù)和名稱空間污染)來(lái)描述這種比較,我們只需傳遞一個(gè)lambda表達(dá)式描述了比較。 讓我們看一下Lambda表達(dá)式的一些屬性

  • 匿名:它仍然可以稱為匿名,因?yàn)樗鼪](méi)有明確的名稱。
  • 簡(jiǎn)潔:正如前面提到的匿名類的情況,與匿名類相比,我們用Lambdas編寫(xiě)的代碼要少得多。
  • 函數(shù):Lambda更像是函數(shù)而不是方法。 這是因?yàn)榉椒▽儆陬?#xff0c;而Lambda不屬于。 但是就像方法一樣,Lambda接受參數(shù)列表,具有主體并且還可以引發(fā)異常。
  • 可以傳遞:Lambda可以傳遞給其他函數(shù),就像普通參數(shù)一樣。

為了消除由于我們上面提到的觀點(diǎn)而引起的任何誤解,lambda不會(huì)添加引入之前的更多功能。 它只是改善了我們編寫(xiě)代碼的方式,并減少了很多樣板代碼。 該樣板代碼甚至與我們用來(lái)通過(guò)基礎(chǔ)操作系統(tǒng)的多核性質(zhì)進(jìn)行代碼識(shí)別的系統(tǒng)級(jí)編程有關(guān)。 讓我們看一下這種簡(jiǎn)單的語(yǔ)法糖如何使我們的工作在并行性,代碼簡(jiǎn)潔性和緊湊性方面更容易。

2.編寫(xiě)Lambda表達(dá)式

在本節(jié)中,我們將看到Java Lambda表達(dá)式如何減少執(zhí)行一些簡(jiǎn)單操作所需編寫(xiě)的代碼行。 例如,我們將比較代碼行數(shù)以構(gòu)成一個(gè)Comparator函數(shù)。 為了進(jìn)行比較,我們將在此處創(chuàng)建一個(gè)簡(jiǎn)單的POJO類,即Student類,其中包含Student ID(作為L(zhǎng)ong和name作為String參數(shù):

學(xué)生.java

public class Student { ??private Long id; private String name; // standard setters and getters }

比較我們?cè)趹?yīng)用程序中定義的POJO對(duì)象是一種非常通用的編程實(shí)踐。 如果我們要比較兩個(gè)Student類對(duì)象,則可以使Comparator像這樣:

匿名類的比較器

Comparator<Student> byId = new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { return s1.getId().compareTo(s2.getId()); } };

這是一個(gè)作為Anonymous類的簡(jiǎn)單Comparator實(shí)現(xiàn),但是當(dāng)使用Lambda完成時(shí),我們會(huì)發(fā)現(xiàn)相同的實(shí)現(xiàn)非常精確和干凈。 讓我們?cè)谶@里看到使用Lambda表達(dá)式完成的相同任務(wù):

pom.xml

Comparator<Student> byId = (s1, s2) -> s1.getId().compareTo(s2.getId());

Lambda表達(dá)式上方也可以稱為塊Lambda表達(dá)式,因?yàn)樗?gt;符號(hào)右側(cè)的單個(gè)代碼塊組成。 它變得更加簡(jiǎn)潔小巧,這聽(tīng)起來(lái)很神奇,請(qǐng)參見(jiàn)以下代碼片段:

Lambda的簡(jiǎn)潔實(shí)現(xiàn)

Comparator<Student> byId = Comparator.comparing(Student::getId);

這是建立比較器的好方法,而且也很簡(jiǎn)單。 對(duì)于上面我們進(jìn)行的Block Lambda表達(dá)式,讓我們將其分為幾部分以更好地理解:

Lambda表達(dá)
  • Lambda Expression以在此情況下傳遞給函數(shù)Comparator的參數(shù)列表開(kāi)頭
  • 箭頭符號(hào)將Lambda Expression參數(shù)與Lambda主體分開(kāi)
  • 主體清楚地將兩個(gè)學(xué)生對(duì)象及其id進(jìn)行比較,該表達(dá)式定義了Lambda返回值

需要注意的是,編譯后的代碼(即匿名類版本和Lambda表達(dá)式版本的字節(jié)碼)將完全相同,因?yàn)長(zhǎng)ambda表達(dá)式僅僅是使代碼清晰的語(yǔ)法。 盡管使用Lambda表達(dá)式有時(shí)可能會(huì)使代碼的可讀性降低。

3. Lambda表達(dá)式與匿名類

我們使用Lambda表達(dá)式編寫(xiě)的代碼也可以使用Anonymous類編寫(xiě),其實(shí)現(xiàn)方式與Lambda Expressions完全相同。 區(qū)別在于Lambda代碼的簡(jiǎn)潔性。

作為比較示例,讓我們構(gòu)造一個(gè)類和一個(gè)將Runnable作為輸入的方法:

可運(yùn)行類

public class RunnableInstance { public static void doSomething(Runnable runnable){ runnable.run(); } }

當(dāng)我們使用Anonymous類制作Runnable時(shí),其外觀如下所示:

可通過(guò)匿名類運(yùn)行

Runnable runnable = new Runnable() { @Override public void run() { System.out.print( "Anonymous class implementation." ); } }; doSomething(runnable);

讓我們嘗試將上面的代碼轉(zhuǎn)換為L(zhǎng)ambda表達(dá)式,看看如何得到干凈的東西:

可與Lambda一起運(yùn)行

Runnable runnable = () -> System.out.print( "Lambda Expression." ); doSomething(runnable);

如果我們不想多次使用可運(yùn)行的實(shí)現(xiàn),我們甚至可以避免進(jìn)行引用:

簡(jiǎn)潔的Lambda Runnable

doSomething(() -> System.out.print( "Lambda Expression." ));

4.使用Lambda表達(dá)式進(jìn)行并行編程

每當(dāng)我們談?wù)摼€程時(shí),我們大多數(shù)人都會(huì)退后一步,考慮是否真的需要在我們的應(yīng)用程序中實(shí)現(xiàn)線程以支持并行性,因?yàn)椴⑿行员举|(zhì)上微不足道且難以管理。 當(dāng)我們有一個(gè)項(xiàng)目集合時(shí),我們實(shí)現(xiàn)了一個(gè)lambda,如:

并行編程

collection.map { // my lambda }

在這里,集合本身能夠與提供的Lambda實(shí)現(xiàn)并行性,而不必自己實(shí)現(xiàn)線程。 這意味著,在多核環(huán)境中,Lambda可以在集合上進(jìn)行流式傳輸時(shí)利用多個(gè)核。 就像我們考慮一個(gè)簡(jiǎn)單的例子一樣:

Lambda與并行流

List<String> names = students.stream() .map(s -> s.getName().toUpperCase()) .collect(Collectors.toList());

map函數(shù)可以在多核環(huán)境中并行運(yùn)行,以一次處理多個(gè)對(duì)象,而無(wú)需我們做任何事情。 為此,僅需要執(zhí)行此程序的操作系統(tǒng)必須是多核。 一旦滿足此條件,我們可以確保可以在給定語(yǔ)句中并行執(zhí)行的任何操作都將自動(dòng)完成。

5.收藏和流

Collections框架是Java中最常用的Framework API之一。 集合允許我們將相似的對(duì)象收集到可以針對(duì)特定目的進(jìn)行優(yōu)化的數(shù)據(jù)結(jié)構(gòu)中。 前面的所有示例都需要對(duì)象的集合,因此,假設(shè)我們有一個(gè)Student類型的對(duì)象的集合,就像我們前面定義的那樣:

學(xué)生集合

List students = getStudentObjectCollection();

我們從添加到Collection接口的新方法stream()開(kāi)始。 由于所有集合都“擴(kuò)展”集合,因此所有Java集合都繼承了此方法:

學(xué)生流

List students = getStudentObjectCollection(); Stream stream = students.stream(); // a stream of student objects

盡管看起來(lái)很像,但Stream接口不是另一種常規(guī)的集合類型。 我們可以將Stream視為“數(shù)據(jù)流”抽象,它使我們能夠轉(zhuǎn)換或操縱其包含的數(shù)據(jù)。 與我們?cè)贘ava中研究過(guò)的其他集合不同,Stream不允許我們直接訪問(wèn)其包含的元素。 盡管如果您想訪問(wèn)元素,我們總是可以將流轉(zhuǎn)換為Java中的集合之一并實(shí)現(xiàn)我們的目的。

出于演示目的,我們將看到如果我們必須計(jì)算students集合中有多少個(gè)奇數(shù)ID對(duì)象,我們的代碼將是什么樣子。 首先,讓我們看看如何在不使用流的情況下完成此操作:

計(jì)數(shù)奇數(shù)

long count = 0 ; List students = getStudentObjectCollection(); for (Student s : students) { if (s.getId() % 2 == 1 ) { count++; } }

使用for循環(huán),我們創(chuàng)建了一個(gè)計(jì)數(shù)器,每次在學(xué)生列表中遇到奇數(shù)ID時(shí),該計(jì)數(shù)器都會(huì)遞增。 對(duì)于一個(gè)非常簡(jiǎn)單的任務(wù),我們已經(jīng)數(shù)百次編寫(xiě)了這種類型的代碼,它跨越多行。

我們也可以在一行中使用Stream編寫(xiě)完全相同的代碼:

使用流

List students = getStudentObjectCollection(); long count = students.stream().filter(student -> student.getId() % 2 == 1 ).count();

這看起來(lái)比以前的for循環(huán)方法干凈整潔嗎? 一切都始于調(diào)用stream()方法,該方法將給定的集合轉(zhuǎn)換為Stream,其他所有調(diào)用都鏈接在一起,因?yàn)?strong>Stream接口中的大多數(shù)方法都是在考慮Builder模式的情況下設(shè)計(jì)的 。 對(duì)于那些不習(xí)慣使用這種方法進(jìn)行鏈接的用戶,可能更容易這樣可視化:

可視化流

List students = getStudentObjectCollection(); Stream stream = students.stream(); stream = stream.filter(student -> student.getId() % 2 == 1 ); long count = stream.count();

讓我們將注意力集中在我們使用的Stream的兩種方法中, filter()和count() 。

filter()方法采用要過(guò)濾集合的條件,該條件由帶一個(gè)參數(shù)并返回布爾值的lambda表達(dá)式表示:

Lambda條件

student -> student.getId() % 2 == 1

并非偶然,用于表示該表達(dá)式的功能接口filter()方法的參數(shù)filter()是謂詞接口。 它只有一個(gè)抽象方法boolean test(T t) :

功能介面

@FunctionalInterface public interface Predicate { boolean test(T t); // non-abstract methods here }

參數(shù)化類型T表示流中元素的類型,即Student對(duì)象。 過(guò)濾之后,剩下的就是調(diào)用count()方法。 沒(méi)什么大不了的,它只是計(jì)算過(guò)濾發(fā)生后我們流中還剩下多少個(gè)對(duì)象(除了過(guò)濾之外,我們還可以有更多的東西)。 count()方法被視為“終端操作”,在調(diào)用該方法后,該流被稱為“已消耗”且無(wú)法再使用。

6. Lambda表達(dá)式的缺點(diǎn)

盡管帶有Lambda Expressions的代碼看起來(lái)非常簡(jiǎn)潔,但是Lambdas也有一些缺點(diǎn)。 讓我們?cè)谶@里研究其中的一些:

  • 無(wú)法處理檢查的異常 :引發(fā)檢查的異常的任何代碼都應(yīng)包裝在try-catch語(yǔ)句中。 但是,即使我們這樣做,也不總是總是清楚拋出的異常發(fā)生了什么。
  • 性能問(wèn)題 :由于JIT不能始終將forEach() + lambda優(yōu)化到與普通循環(huán)相同的程度,因此Lambda可以在很小程度上影響性能。
  • 調(diào)試挑戰(zhàn) :顯然,使用Lambdas時(shí),代碼并不總是那么簡(jiǎn)潔。 這使得在代碼和可讀性方面發(fā)生的異常的堆棧跟蹤變得有些困難。

盡管Lambda有一些缺點(diǎn),但是當(dāng)您編寫(xiě)簡(jiǎn)潔的代碼時(shí),它們?nèi)匀皇且粋€(gè)很好的伴侶。

7.結(jié)論

Java Lambda表達(dá)式在所有LISP,Perl,Python以及最新版本的C ++,Objective C,C#和Java 8中都出現(xiàn)(具有不同的語(yǔ)法),但值得注意的是,即使它可以處理傳遞的函數(shù)(或一些借口)作為參數(shù)。 它們是具有特定語(yǔ)義的語(yǔ)法元素,并且這些語(yǔ)義對(duì)運(yùn)行時(shí)的要求比C所設(shè)計(jì)的要高。

在本課中 ,我們可以閱讀有關(guān)Lambda表達(dá)式的更多信息,它與功能接口有很深的聯(lián)系,還演示了將并行流與Lambda表達(dá)式配合使用的性能比較,并加深了對(duì)Lambda表達(dá)式如何與功能接口一起使用并可以在簡(jiǎn)單語(yǔ)句中使用的理解。利用多核操作系統(tǒng)提供的并行性,而無(wú)需了解幕后工作的API。

上次更新時(shí)間為2020年2月17日

翻譯自: https://www.javacodegeeks.com/lambda-expressions-java-tutorial.html

總結(jié)

以上是生活随笔為你收集整理的Lambda表达式Java教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。