【javaSE-語法】lambda表達式

【javaSE-語法】lambda表達式

  • 1. 先回憶一下:
    • 1.1 接口不能直接通過關鍵字new進行實例化
    • 1.2 函數式接口
    • 1.3 匿名內部類
      • 1.31 匿名內部類在代碼中長啥樣?
      • 1.32 構造一個新的對象與構造一個擴展了某類的匿名內部類的對象,兩者有什么區別?
      • 1.33 如何調用匿名內部類對象中的成員
      • 1.34 匿名內部類的變量捕獲
  • 2. lambda表達式
    • 2.1 語法
    • 2.2 基本使用
    • 2.3 lambda的變量捕獲
    • 2.4 lambda在集合中的使用
      • 2.41 Collection接口下的forEach()方法和lambda的夢幻聯動
      • 2.42 List接口下的sort()方法和lambda的夢幻聯動
  • 4. lambda表達式的優缺點

1. 先回憶一下:

1.1 接口不能直接通過關鍵字new進行實例化

  1. 接口是引用數據類型,代碼中使用interface定義一個接口。接口中的成員變量默認被public static final修飾,接口中的成員方法默認被public abstract修飾,抽象方法沒有具體的實現。

  2. 接口中成員方法如果用defaul或者static修飾,該成員方法可以有具體的實現。

    • 接口不能通過new關鍵字進行實例化:在這里插入圖片描述

    • 類通過關鍵字implement實現接口,類實現接口后,要重寫接口中的所有抽象方法。通過實例化(實現了某接口的)類,間接實例化某接口在這里插入圖片描述

  3. 接口間可以通過關鍵字extends進行拓展,即把多個接口合并在一起。在這里插入圖片描述

1.2 函數式接口

如果一個接口中有且只有一個抽象方法,那么該接口就是一個函數式接口。在這里插入圖片描述

  1. 在寫代碼時,如果在某個接口上聲明了@FunctionalInterface,表示該接口必須是一個函數式接口,否則程序編譯會報錯。
  2. 下面這種也是函數式接口:
    在這里插入圖片描述

1.3 匿名內部類

1.31 匿名內部類在代碼中長啥樣?

如果一個類定義在類的內部或者方法的內部,該類就是內部類。根據內部類在代碼中的位置,內部類可以分為成員內部類和局部內部類。成員內部類與外部類成員所處位置相同,局部內部類定義在方法內部。在這里插入圖片描述
匿名內部類和局部內部類一樣,都在方法內部,且匿名內部類必須實現接口或者繼承其他類。

我們在寫代碼的時候,如果想在方法內部創建一個類,但是不會用到該類的名字,此時就可以使用匿名內部類。如上述代碼中的兩個匿名內部類:

  • 第一個匿名內部類的意思是:有一個沒有名字的類,該類實現了A接口,并且重寫了A接口中的testA方法。在這里插入圖片描述

  • 如果用局部內部類實現,代碼如下:在這里插入圖片描述

  • 第二個匿名內部類的意思是:有一個沒有名字的類,該類繼承了類B,但沒有進行擴展。(一般都要進行擴展,即添加新的成員,否則該匿名內部類無意義)。在這里插入圖片描述

  • 如果用局部內部類實現,代碼如下:在這里插入圖片描述

1.32 構造一個新的對象與構造一個擴展了某類的匿名內部類的對象,兩者有什么區別?

如果構造參數列表的,結束小括號后面跟一個開始大括號,就是在定義匿名內部類對象。在這里插入圖片描述

1.33 如何調用匿名內部類對象中的成員

在這里插入圖片描述

1.34 匿名內部類的變量捕獲

在匿名內部類中,不僅能訪問外部類的字段,還能訪問局部變量。但是無論是字段還是局部變量,都只能是一旦賦值絕不會改變的變量或者被final修飾的常量。

2. lambda表達式

lambda表達式是匿名內部類的簡化。說的再詳細一點,lambda表達式創建了一個類,實現了一個接口,重寫了接口的方法

看下面代碼,在代碼中對象priorityQueue和對象priorityQueue1完全一樣,但是顯然,創建priorityQueue1的代碼要更加簡潔。這是因為創建priorityQueue的時候,構造方法的參數是一個匿名內部類,而創建priorityQueue1的時候,構造方法的參數一個lambda表達式。
所以,使用lambda表達式能讓能讓代碼更加簡潔,開發也隨之更加迅速,這就是我們學習lambda表達式的原因。
在這里插入圖片描述

2.1 語法

lambda表達式的語法: (parameters) -> expression 或 (parameters) ->{ statements; }

  1. parameters是參數,根據實際情況,參數可以有,也可以沒有。這里的參數等同于方法的參數列表。
    • 參數的數據類型可以明確聲明,也可以不聲明而是讓JVM推斷。如果要省略,每個參數的數據類型都要省略。
    • 當只有一個沒有聲明類型的參數時,可以省略外面的小括號()。
  2. expression是表達式,是函數式接口里方法的實現。
  3. statements;是代碼塊,是函數式接口里方法的實現。這里的代碼塊和表達式等同于方法里面的方法體。
    • 如果方法體中只有一條代碼,大括號{}可以省略
    • 如果方法體中只有一條語句,且是return語句,大括號和關鍵字return可同時省略。

例如:

// 1. 不需要參數,返回值為 2
() -> 2
// 2. 接收一個參數(數字類型),返回其2倍的值
x -> 2 * x
// 3. 接受2個參數(數字),并返回他們的和
(x, y) -> x + y
// 4. 接收2個int型整數,返回他們的乘積
(int x, int y) -> x * y
// 5. 接受一個 string 對象,并在控制臺打印,不返回任何值(看起來像是返回void)
(String s) -> System.out.print(s)

2.2 基本使用

接下來跟著具體場景看看lambda表達式在代碼中究竟如何使用:

  1. 已知函數式接口NoParameterNoReturn,接口中的test()方法沒有參數,沒有返回值。如何調用接口中的test()方法呢?在這里插入圖片描述運行結果:
    在這里插入圖片描述
  2. 下面是使用lambda表達式的更多例子:
public class Test {public static void main1(String[] args) {//如何調用接口NoParameterNoReturn中的test方法?//不使用lambda表達式(通過匿名內部類實現接口,重寫方法):NoParameterNoReturn noParameterNoReturn =new NoParameterNoReturn() {@Overridepublic void test() {System.out.println("test......");}};noParameterNoReturn.test();//使用lambda表達式NoParameterNoReturn noParameterNoReturn1 =()-> System.out.println("test......");//重寫接口中的方法,該方法沒有參數,沒有返回值noParameterNoReturn1.test();}public static void main2(String[] args) {//如何調用接口OneParameterNoReturn中的test方法?OneParameterNoReturn oneParameterNoReturn = (x)->{System.out.println(x);};//只有一個沒聲明類型的參數,小括號()可以省略;方法體中只有一條語句,{}可以省略oneParameterNoReturn.test(10);//如何調用接口MoreParameterNoReturn中的test()方法?test()方法無返回值但是有多個參數MoreParameterNoReturn moreParameterNoReturn =(int x,int y) -> {System.out.println(x+y);};moreParameterNoReturn.test(10,20);}public static void main(String[] args) {//如何調用接口NoParameterReturn中的test方法?test方法中有返回值,無參數NoParameterReturn noParameterReturn =() -> {return 10;};//return和{}可同時省略System.out.println(noParameterReturn.test());//如何調用接口OneParameterReturn中的test方法?test方法中有返回值,有一個參數OneParameterReturn oneParameterReturn = x -> x;oneParameterReturn.test(20);//傳20返回20//如何調用接口MoreParameterReturn中的test方法?test方法中有返回值,有多個參數MoreParameterReturn moreParameterReturn =(a,b) -> {return a*b;};moreParameterReturn.test(10,20);//返回200}
}
//無返回值無參數
@FunctionalInterface
interface NoParameterNoReturn {void test();
}
//無返回值一個參數
@FunctionalInterface
interface OneParameterNoReturn {void test(int a);
}
//無返回值多個參數
@FunctionalInterface
interface MoreParameterNoReturn {void test(int a,int b);
}
//有返回值無參數
@FunctionalInterface
interface NoParameterReturn {int test();
}
//有返回值一個參數
@FunctionalInterface
interface OneParameterReturn {int test(int a);
}
//有返回值多參數
@FunctionalInterface
interface MoreParameterReturn {int test(int a,int b);
}

所以如果想在代碼中使用lambda表達式,一定要清楚函數式接口中要被重寫的方法,該方法中是否有返回值,是否有參數

2.3 lambda的變量捕獲

同匿名內部類的變量捕獲一樣,lambda表達式內不僅能訪問外部類的字段,還能訪問局部變量。但是無論是字段還是局部變量,都只能是一旦賦值絕不會改變的變量或者被final修飾的常量。

例如在下面代碼中:
在這里插入圖片描述在多線程編程中,經常會用到lambda表達式,尤其要注意變量捕獲這一點,如果在lambda表達式這種用了某變量,但在后續又修改了該變量,代碼就會出現問題。

2.4 lambda在集合中的使用

lambda表達式是JavaSE8中的一個重要的新特性。為了能讓Lambda和Java的集合類集更好的一起使用,集合當中,也新增了部分接口,以便與Lambda表達式對
接。

對應的接口新增的方法
CollectionremoveIf() spliterator() stream() parallelStream() forEach()
ListreplaceAll() sort()
MapgetOrDefault() forEach() replaceAll() putIfAbsent() remove() replace() computeIfAbsent() computeIfPresent() compute() merge()

接下來會分別演示在Collection接口forEach() 方法中,在List接口sort()方法中,分別如何使用lambda表達式。

其他方法在遇到時,查看Java幫助手冊或查看對應源碼,同樣的方法學習掌握即可。

2.41 Collection接口下的forEach()方法和lambda的夢幻聯動

  1. 先找到Collection接口下forEach()方法中的函數式接口:

Collection接口拓展了Iterable接口,在這里插入圖片描述

forEach()方法在Iterable接口中,
在這里插入圖片描述
forEach()方法的源碼如下:從源碼中看出,forEach()方法的功能就是遍歷當前集合中的元素,然后讓每個元素執行action.accept()操作
在這里插入圖片描述
forEach()方法的參數action的類型是一個函數式接口,其中的void accept(T t)抽象函數,有一個參數無返回值。
在這里插入圖片描述所以當我們調用forEach()方法的時候,forEach()方法的參數是一個函數式接口action,我們需要實現該接口并且重寫接口中的accept()的方法。此時我們可以使用匿名內部類或者lambda表達式:

  1. 例如下列代碼:

在這里插入圖片描述

2.42 List接口下的sort()方法和lambda的夢幻聯動

  1. 先找到List接口下sort()方法中涉及的函數式接口:

sort()方法的源碼如下:
從源碼中看出,sort()方法的功能就是先調用Arrays工具包中的sort方法,并依據比較器c的規則對當前容器元素進行排序。然后再對已經排好序的當前容器進行迭代操作。
在這里插入圖片描述
sort方法的參數c的類型是一個函數式接口,其中的int compare(T o1, T o2)抽象函數,有兩個參數有返回值。
函數式接口Comparator所以當我們調用sort()方法的時候,sort()方法的參數是一個函數式接口c,我們需要實現該接口并且重寫接口中的compare()的方法。此時我們可以使用匿名內部類或者lambda表達式:

2.例如下面代碼:
在這里插入圖片描述

4. lambda表達式的優缺點

Lambda表達式的優點很明顯,在代碼層次上來說,使代碼變得非常的簡潔。缺點也很明顯,代碼不易讀。

優點:

  1. 代碼簡潔,開發迅速
  2. 方便函數式編程
  3. 非常容易進行并行計算
  4. Java 引入 Lambda,改善了集合操作

缺點:

  1. 代碼可讀性變差
  2. 在非并行計算中,很多計算未必有傳統的 for 性能要高
  3. 不容易進行調試


好了,本篇到這就結束了,相信讀完本篇的你已經能讀懂,會用lambda表達式了。最后祝你我早日成為技術流。

我是一朵忽明忽暗的云,點贊收藏加關注,我們一起進步!
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/716438.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/716438.shtml
英文地址,請注明出處:http://en.pswp.cn/news/716438.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

maven--->maven中的<properties>屬性有什么作用?

🙌🙌🙌🙌🙌🙌 在Maven中,元素用于定義項目中可重用的屬性值。這些屬性值可以在項目的POM文件中被引用,以便在整個項目中統一管理和使用。通過使用元素,可以避免在POM文件…

SpringBean生命周期之InitializingBean,初始化bean

1 yml文件 weixin:appid: aaaaaapartner: 12313214partnerkey: ccccccert: C:\\Users\\lenovo\\Desktop 2 Bean初使化 import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframewor…

midjourney提示詞語法

更高級的提示可以包括一個或多個圖像URL、多個文本短語和一個或更多個參數 Image Prompts 可以將圖像URL添加到提示中,以影響最終結果的樣式和內容。圖像URL總是位于提示的前面。 https://docs.midjourney.com/image-prompts Text Prompt 要生成的圖像的文本描述。…

YOLOv6、YOLOv7、YOLOv8網絡結構圖(清晰版)

承接上一篇博客:YOLOv3、YOLOv4、YOLOv5、YOLOx的網絡結構圖(清晰版)_yolox網絡結構圖-CSDN博客 1. YOLOv6網絡結構圖 2. YOLOv7網絡結構圖 3. YOLOv8網絡結構圖

搭建 LNMP 架構

一 理論知識 (一)架構圖 (二)CGI 由來 最早的Web服務器只能簡單她響應瀏覽器發來的HTTP請求,并將存儲在服務器上的HTML文件返回給瀏覽器,也就是靜態html文件,但是后期隨著網站功能增多網站開…

c++階梯之模板初階

1. 泛型編程 void Swap(int& x, int& y) {int tmp x;x y;y tmp; }void Swap(double& x, double& y) {double tmp x;x y;y tmp; }void Swap(char& x, char& y) {char tmp x;x y;y tmp; } int main() {int a 10, b 20;double c 1.1, d 2.2…

《Spring Security 簡易速速上手小冊》第7章 REST API 與微服務安全(2024 最新版)

文章目錄 7.1 保護 REST API7.1.1 基礎知識詳解7.1.2 重點案例:使用 JWT 進行身份驗證和授權案例 Demo 7.1.3 拓展案例 1:API 密鑰認證案例 Demo測試API密鑰認證 7.1.4 拓展案例 2:使用 OAuth2 保護 API案例 Demo測試 OAuth2 保護的 API 7.2 …

讀書筆記-三國演義-夏侯惇

夏侯惇(公元夏侯惇(公元190年-公元220年),字元讓,沛國譙縣(今安徽亳州市)人,是中國東漢末年至三國時期魏國重要將領之一。他是曹操麾下的得力將領,以勇猛忠誠而聞名于世。…

linux安裝matlab獲取許可證

1.點擊許可證 2. 3. 4. 4.主機ID 打開linux輸入 /sbin/ifconfigether后邊的就是 6.計算機登錄名 打開linux輸入 whoami7. 8. 9.

局域網https自簽名教程

們的客戶是在內網環境里面,所以就只能用自簽名證書來搞,我一想這還不容易,就迅速的百度了一下隨便找了個文章開始照貓畫虎,很快就弄完了,但是弄完后發現還是有問題,而且https 還是報不安全, 1、…

(規劃)24屆春招和25屆暑假實習路線準備規劃

春招&&暑假實習: 1.八股: 可以去一些八股網站上面進行閱讀。 2.項目:至少準備1-2個項目,可以條理清晰的進行項目介紹和難點剖析。 3.算法: hot100 ,劍指offer 能刷的很熟,算法關就差…

【R包報錯】使用sceasy包轉換rds文件與h5ad文件報錯PyType_GetFlags

想要將scanpy的h5ad文件轉為rds文件,有一個很方便的包sceasy可以使用,安裝簡單,代碼簡易。 安裝方式 # bioconda package:conda install -c bioconda r-sceasy# R package:devtools::install_github("cellgeni/sceasy")#額外需要…

android系統開發之--ROM編譯,repo使用指南

1、檢出代碼&#xff0c;指定git指定的分支和manifest repo init -u git://xxx/xxx/manifest.git -b <BRANCH> -m <MANIFEST> 這里-m和-b的含義是&#xff1a; 1. 注意到manifest.git本身也是一個git project 2. 所以&#xff0c;-b指定的是使用#1中這個git proj…

我的相關獎項

博士錄取證明 名單第53&#xff1a;https://yzb.bupt.edu.cn/content/content.php?p2_2_651 論文鏈接 第一篇&#xff1a;https://doi.org/10.1186/s13677-022-00373-8 第二篇&#xff1a;https://doi.org/10.1016/j.ipm.2022.103167 第三篇&#xff1a;https://doi.org/10…

Unity 腳本-生命周期常用函數

在Unity中&#xff0c;萬物皆是由組件構成的。 右鍵創建C&#xff03;腳本&#xff0c;拖動腳本到某物體的組件列表。 生命周期相關函數 using System.Collections; using System.Collections.Generic; using UnityEngine;// 必須要繼承 MonoBehaviour 才是一個組件 // 類名…

matplotlib——散點圖和條形圖(python)

散點圖 需求 我們獲得北京2016年三月和十月每天白天最高氣溫&#xff0c;我們現在需要找出氣溫隨時間變化的某種規律。 代碼 # 導入庫 from matplotlib import pyplot as plt import random# 解決中文亂碼 import matplotlib matplotlib.rc("font",family"F…

【筆記】-編程語言以及應用領域

C/C 永遠不會衰敗的語言&#xff0c;適合偏底層&#xff0c;例如&#xff1a;Windows操作系統80%以上都是由C/C完成的&#xff0c;C/C也集成用于寫應用層C/S架構的軟件 JAVA 是真正的跨平臺的語言 “一次編程&#xff0c;到處使用”Java適合應用層的開發&#xff0c;無論是…

Python的錯誤和異常

文章目錄 python的語法錯誤異常異常處理用戶自定義異常定義清理行為預定義的清理行為 python的語法錯誤 語法錯誤&#xff08;Syntax Error&#xff09;是指代碼不符合Python語言的語法規則。當解釋器在執行代碼之前對其進行解析時&#xff0c;如果發現代碼中有語法錯誤&#…

領域驅動設計(Domain-Driven Design DDD)——戰略設計1

一、概述 隨著系統的增長&#xff0c;它會越來越復雜&#xff0c;當我們無法通過分析對象來理解系統的時候&#xff0c;就需要掌握一些操縱和理解大模型的技術了。 最負雄心的企業欲實現一個涵蓋所有業務、緊密集成的系統。因大型公司的業務模型巨大且復雜&#xff0c;很難把它…

2403d,d的108版本更改

原文 編譯器更改 1,在object.d中給TypeInfo_Class添加了.nameSig字段 2,總是在調用點求值像__FILE__此類關鍵字 3,現在可按整數數組轉換十六進制串 4,添加支持插值式序列 庫更改 1,isForwardRange,isBidirectionalRange和isRandomAccessRange現在帶可選元素類型 2,std.uni已…