Java基礎---lambda表達式

一、為什么要引入lambda表達式

????????lambda 表達式是一個可傳遞的代碼塊 可以在以后執行一次或多次
? ? ? ? 在介紹lambda表達式之前,我們看一下,以前,我們對于一個問題的通常寫法。
????????
? ? ? ? 假設你已經了解了如何按指定時間間隔完成工作,當然不了解也沒關系,只是作為例子說明。 將這個工作放在一個 ActionListener 的 actionPerformed 方法中
class Worker implements ActionListener
{public void actionPerformed(ActionEvent event){// do some work}
}
????????想要反復執行這個代碼時, 可以構造 Worker 類的一個實例 然后把這個實例提交到一個 Timer 對象 這里的重點是 actionPerformed 方法包含希望以后執行的代碼
????????或者可以考慮如何用一個定制比較器完成排序。 如果想按長度而不是默認的字典順序對
字符串排序 可以向 sort 方法傳人一個 Comparator 對象
class LengthComparator implements Comparator<String>
{public int compare(String first, String second){return first.length() - second.length();}
}
????????這兩個例子有一些共同點, 都是將一個代碼塊傳遞到某個對象 一個定時器 或者一個 sort 方法)。這個代碼塊會在將來某個時間調用。
????????到目前為止, Java 中傳遞一個代碼段并不容易 不能直接傳遞代碼段 。 ? Java 是一種面
向對象語言 所以必須構造一個對象 這個對象的類需要有一個方法能包含所需的代碼。
????????在其他語言中, 可以直接處理代碼塊 Java 設計者很長時間以來一直拒絕增加這個特性 。 畢竟, Java 的強大之處就在于其簡單性和一致性 如果只要一個特性能夠讓代碼稍簡潔一些 , 就把這個特性增加到語言中, 這個語言很快就會變得一團糟 無法管理 。 不過 在另外那些 語言中, 并不只是創建線程或注冊按鈕點擊事件處理器更容易 它們的大部分 API 都更簡單 、 更一致而且更強大。 Java 也可以編寫類似的 API 利用類對象實現特定的功能 不過這種 API 使用可能很不方便

二、lambda表達式的語法

????????再來考慮上面討論的排序例子。 我們傳入代碼來檢查一個字符串是否比另一個字符串短。 這里要計算
????????first. length()? - second . length()
????????first second 是什么 它們都是字符串 Java 是一種強類型語言 所以我們還要指定它 們的類型:
????????(String first, String second)
????????????????-> first.length()?- second.length()
????????這就是一個lambda表達式。lambda 表達式就是一個代碼塊 以及必須傳入代碼的變量規范。
????????你已經見過 Java 中的一種 lambda 表達式形式 參數 箭頭 - > ) 以及一個表達式 如果代碼要完成的計算無法放在一個表達式中, 就可以像寫方法一樣 把這些代碼放在 {} , 并包含顯式的 return 語句 例如

????????即使 lambda 表達式沒有參數 仍然要提供空括號 就像無參數方法一樣

????????如果可以推導出一個 lambda 表達式的參數類型 則可以忽略其類型 例如

????????在這里, 編譯器可以推導出 first second 必然是字符串 因為這個 lambda 表達式將賦給一個字符串比較器。
????????如果方法只有一個參數 而且這個參數的類型可以推導得出 那么甚至還可以省略小括號

????????無需指定 lambda 表達式的返回類型 lambda 表達式的返回類型總是會由上下文推導得出。 例如 下面的表達式:

????????可以在需要 int? 類型結果的上下文中使用
????????如果一個 lambda 表達式只在某些分支返回一個值 而在另外一些分支不返回值 , 這是不合法的。 例如 int x ) - > { if ( x > = 0 ) return 1 ; } 就不合法

? ? ? ? 代碼示例:

package FunctionProm;import javax.swing.*;
import java.util.Arrays;
import java.util.Date;public class LambdaTest {public static void main(String[] args) {String[] planets = new String[] { "Mercury" , "Venus" , "Earth" , "Mars" , "Jupiter" , "Saturn" , "Uranus" , "Neptune" };System.out.println(Arrays.toString(planets));System.out. println("Sorted in dictionary order:") ;Arrays.sort(planets);System.out.println (Arrays.toString(planets));System.out . println ("Sorted by length:");Arrays.sort(planets, (first, second) -> first.length() - second.length()) ;System.out. println(Arrays.toString(planets));Timer t = new Timer(1000, event ->System.out.println ("The time is " + new Date()));t.start();// keep program running until user selects "0k"JOptionPane.showMessageDialog (null , "Quit program?");System.exit(0);}
}

三、函數式接口

????????前 面 已 經 討 論 過, Java 中 已 經 有 很 多 封 裝 代 碼 塊 的 接 口 ActionListener 或 Comparatorlambda 表達式與這些接口是兼容的。
????????對于只有一個抽象方法的接口, 需要這種接口的對象時 就可以提供一個 lambda 表達式。 這種接口稱為函數式接口 functional interface )
????????為了展示如何轉換為函數式接口, 下面考慮 Arrays . sort 方法 它的第二個參數需要一個 Comparator 實例 Comparator 就是只有一個方法的接口 所以可以提供一個 lambda 表達式

????????在底層, Arrays . sort 方法會接收實現了 Comparator < String > 的某個類的對象 。 在這個對象上調用 compare 方法會執行這個 lambda 表達式的體。這些對象和類的管理完全取決于具體實現, 與使用傳統的內聯類相比,這樣可能要高效得多。最好把 lambda 表達式看作是一個函數,而不是一個對象, 另外要接受 lambda 表達式可以傳遞到函數式接口。
????????lambda 表達式可以轉換為接口 ,這一點讓 lambda 表達式很有吸引力 具體的語法很簡短。 下面再來看一個例子

????????與使用實現了 ActionListener 接口的類相比 這個代碼可讀性要好得多
????????實際上, 在 Java 中, lambda 表達式所能做的也只是能轉換為函數式接口 在其他支 持函數字面量的程序設計語言中, 可以聲明函數類型 String , String ) - > int ) 聲明這些類 型的變量, 還可以使用變量保存函數表達式 不過 Java 設計者還是決定保持我們熟悉的接口概念, 沒有為Java 語言增加函數類型
????????Java API java . util . fimction 包中定義了很多非常通用的函數式接口 其中一個接口BiFunction< T , U , R > 描述了參數類型為 T U 而且返回類型為 R 的函數 可以把我們的字符串比較 lambda 表達式保存在這個類型的變量中

????????不過, 這對于排序并沒有幫助 沒有哪個 Arrays . sort 方法想要接收一個 BiFunction 如果你之前用過某種函數式程序設計語言, 可能會發現這很奇怪 不過 對于 Java 程序員而言, 這非常自然 類似 Comparator 的接口往往有一個特定的用途 而不只是提供一個有指定參數和返回類型的方法。 Java SE 8 沿襲了這種思路 想要用 lambda 表達式做某些處理 還是要謹記表達式的用途, 為它建立一個特定的函數式接口
????????java . util . function 包中有一個尤其有用的接口 Predicate :

????????ArrayList 類有一個 removelf 方法 它的參數就是一個 Predicate 這個接口專門用來傳遞 lambda 表達式 例如 下面的語句將從一個數組列表刪除所有 null
????????list. removelf ( e - > e = = null ) ;

????????四、方法引用

????????有時, 可能已經有現成的方法可以完成你想要傳遞到其他代碼的某個動作 例如 假設你希望只要出現一個定時器事件就打印這個事件對象。 當然 為此也可以調用 :

????????但是, 如果直接把 println 方法傳遞到 Timer 構造器就更好了 具體做法如下

????????表達式 System . out :: println 是一個方法引用 method reference ) , 它等價于 lambda 表達式 x 一 > System . out . println ( x )
????????再來看一個例子, 假設你想對字符串排序 而不考慮字母的大小寫 可以傳遞以下方法表達式:

????????從這些例子可以看出, 要用:: 操作符分隔方法名與對象或類名 主要有 3 種情況

????????在前 2 種情況中 方法引用等價于提供方法參數的 lambda 表達式 前面已經提到 , System. out :: println 等價于 x - > System . out . println ( x)。 類似地, Math : : pow 等價于 x y ) - >
Math . pow ( x , y)。
????????對于第 3 種情況 第 1 個參數會成為方法的目標 例如 String : : compareToIgnoreCase
同于 ( x , y ) - > x . compareToIgnoreCase ( y ) 。
????????如果有多個同名的重栽方法, 編譯器就會嘗試從上下文中找出你指的那一個方法 。 例如, Math . max 方法有兩個版本 一個用于整數 另一個用于 double 選擇哪一個版 本取決于 Math :: max 轉換為哪個函數式接口的方法參數 類似于 lambda 表達式 方法引用不能獨立存在, 總是會轉換為 函數式接口 的實例
????????可以在方法引用中使用 this 參數 例如 this :: equals 等同于 x - > this . equals ( x ) 使用
super 也是合法的 下面的方法表達式:
????????super: : instanceMethod
????????使用 this 作為目標 會調用給定方法的超類版本
為了展示這一點 下面給出一個假想的例子

????????TimedGreeter. greet 方法開始執行時 會構造一個 Timer , 它會在每次定時器滴答時執行 super:: greet 方法 這個方法會調用超類的 greet 方法

????????五、構造器引用

????????構造器引用與方法引用很類似, 只不過方法名為 new 例如 Person : : new Person 構造 器的一個引用。 哪一個構造器呢 這取決于上下文 假設你有一個字符串列表 可以把它轉換為一個 Person 對象數組 為此要在各個字符串上調用構造器 調用如下

????????map 方法會為各個列表元素調用 Person ( String ) 構造器 如果有多個 Person 構造器 編譯器會選擇有一個 String 參數的構造器 因為它從上下文推導出這是在對一個字符串調用構造器。
????????可以用數組類型建立構造器引用。 例如 int [] :: new 是一個構造器引用 它有一個參數 :即數組的長度。 這等價于 lambda 表達式 x - > new int [ x ]。
????????Java 有一個限制 無法構造泛型類型 T 的數組 數組構造器引用對于克服這個限制很有用。 表達式 new T [ n ] 會產生錯誤 因為這會改為 new Object [ n]。
????????對于開發類庫的人來說, 這是一個問題。 例如 假設我們需要一個 Person 對象數組。
????????Stream 接口有一個 toArray 方法可以返回 Object 數組

????????不過, 這并不讓人滿意 用戶希望得到一個 Person 引用數組 而不是 Object 引用數組 。流庫利用構造器引用解決了這個問題。 可以把 Person [ ] : : new 傳入 toArray 方法

????????toArray方法調用這個構造器來得到一個正確類型的數組 然后填充這個數組并返回

????????六、變量作用域

????????通常, 你可能希望能夠在 lambda 表達式中訪問外圍方法或類中的變量 考慮下面這個例子:
public static void repeatMessage(String text, int delay)
{ActionListener listener = event ->{System.out.println(text);Toolkit.getDefaultToolkit().beep():};new Timer(delay, listener).start();
}

????????來看這樣一個調用

????????現在來看 lambda 表達式中的變量 text 注意這個變量并不是在這個 lambda 表達式中定義的。 實際上 這是 repeatMessage 方法的一個參數變量
????????如果再想想看, 這里好像會有問題 盡管不那么明顯 lambda 表達式的代碼可能會在 repeatMessage 調用返回很久以后才運行 而那時這個參數變量已經不存在了 如何保留 text
變量呢
????????要了解到底會發生什么, 下面來鞏固我們對 lambda 表達式的理解 lambda 表達式有 3 個部分:
????????1 ) 一個代碼塊
????????2 ) 參數 ;
????????3 ) 自由變量的值 這是指非參數而且不在代碼中定義的變量
????????在我們的例子中, 這個 lambda 表達式有 1 個自由變量 text 表示 lambda 表達式的數據結構必須存儲自由變量的值, 在這里就是字符串 " Hello " 我們說它被 lambda 表達式捕獲(下面來看具體的實現細節 例如 可以把一個 lambda 表達式轉換為包含一個方法的對象, 這樣自由變量的值就會復制到這個對象的實例變量中

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

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

相關文章

js字符串轉json的3種方法

1.eval方式解析 function strToJson(str){var json eval("(" str ")");return json;}console.log(strToJson("{int:1, string:demo}")); 運行截圖&#xff1a; 注&#xff1a; 記得別忘了str兩旁的小括號。 永遠不要使用 eval !!! eval() 是一…

611. 有效三角形的個數 - 力扣

1. 題目 給定一個包含非負整數的數組 nums &#xff0c;返回其中可以組成三角形三條邊的三元組個數。 2. 示例 3. 分析 利用已升序了的數組通過 a b > c 這條公式找出符合要求的三元組&#xff0c;利用這個公式的前提是三條邊為從小到大&#xff0c;再利用單調性快速統計…

STM32 (1)

1.基本信息 stm32是由ST公司生產的一種32位微控制器&#xff08;單片機&#xff09;。 1.1 各種型號 stm32是32位單片機的總稱&#xff0c;有多種不同的系列。 32即用32個比特位表示一個地址&#xff0c;尋址范圍&#xff1a;0x00000000 --0xffffffff (4GB) 1.2 存儲密度 …

Mysql事務的兩段式提交

binlog和redo log區別 為了滿足Mysql的事物ACID特性&#xff0c;InnoDB引入了redo log和 undo log日志文件。為了滿足主從同步Mysql引入了binlog日志文件。redo log和binlog文件都保存的數據庫對數據庫的修改&#xff0c;但是binlog和redo log本質上是不一樣的&#xff1a; r…

UE5中實現后處理深度描邊

后處理深度描邊可以通過取得邊緣深度變化大的區域進行描邊&#xff0c;一方面可以用來做角色的等距內描邊&#xff0c;避免了菲尼爾邊緣光不整齊的問題&#xff0c;另一方面可以結合場景掃描等特效使用&#xff0c;達到更豐富的效果&#xff1a; 后來解決了開啟TAA十字線和鋸齒…

XXL-Job的基本使用

一、市面上常見的任務調度產品 針對分布式任務調度的需求&#xff0c;市場上出現了很多的產品: 其中XXL-job 是我們經常使用的任務調度平臺,XXL這三個英文字母.是以作者名許雪里命名的。 可以前往 Gitee 地址進行下載使用 https://gitee.com/xuxueli0323/xxl-job.git二、XXL-J…

使用`paddle.nn.Layer`自定義網絡教程

文章目錄 使用paddle.nn.Layer自定義網絡教程1. 概念介紹2. 數據處理3. 搭建一個完整的深度學習網絡4. 使用paddle.nn.Layer構建深度學習網絡5. 利用paddle.nn.Layer進行子層的訪問6. 修改paddle.nn.Layer層的成員變量7. 存儲模型的參數8. 總結 使用paddle.nn.Layer自定義網絡教…

LockBit病毒入侵揭秘:如何防范與應對

在數字時代&#xff0c;隨著科技的飛速發展&#xff0c;網絡安全問題愈發凸顯。惡意軟件和勒索軟件等網絡威脅正不斷演變&#xff0c;其中一款備受關注的勒索軟件就是LockBit。本文將深入介紹LockBit的特征、攻擊手段、演進歷程以及對網絡安全的威脅。 01 主要特征 LockBit是…

算法知識(java)隨筆

1: 保留指定的小數為 printf("%.2f\n", ret) 和c語言類似 // 怎么保留小數 System.out.printf("%.2f\n", 1.0/3); 2: 在寫小數二分的時候 加入讓結果保留6位數 那么 while(r - l > 1e-8) 3: java Map里面之前寫的代碼: /*** 也就是 統計x在map里面的…

第二十一周周報

文獻閱讀&#xff1a;Recent Advances of Monocular 2D and 3D Human Pose Estimation: A Deep Learning Perspective 摘要&#xff1a;在本文中&#xff0c;作者提供了一個全面的 2d到3d視角來解決單目人體姿態估計的問題。首先&#xff0c;全面總結了人體的二維和三維表征。…

騰訊云Windows輕量應用服務器的默認密碼是什么,以及如何重置?

首先&#xff0c;騰訊云輕量應用服務器的默認用戶名是沒有設置密碼的&#xff0c;首次登錄時需要重置密碼。這意味著如果你的輕量應用服務器是騰訊云的&#xff0c;那么默認密碼是不存在的&#xff0c;需要通過重置密碼來獲得一個新的密碼。 關于如何重置密碼&#xff0c;有幾…

chatgpt新版本api的調用

chatgpt新版本api的調用 原始版本調用api方式&#xff1a;新版調用chatgpt-api的方式&#xff1a; 原始版本調用api方式&#xff1a; import openaiopenai.api_key "{上面復制的key}"completion openai.ChatCompletion.create(model"gpt-3.5-turbo",mes…

Spring El表達式官方文檔學習

文章目錄 推薦一、概述1、什么是SpEL2、SpEL能做什么 二、SpEL表達式使用1、文字表達式2、屬性, 數組, List, Map,和 索引&#xff08;1&#xff09;屬性操作&#xff08;2&#xff09;數組和List&#xff08;3&#xff09;Map 3、內嵌List4、內嵌Map5、構建數組6、調用類的方法…

Windows的Linux化持續推進中

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

Java基礎 - 6 - 面向對象(二)

Java基礎 - 6 - 面向對象&#xff08;一&#xff09;-CSDN博客 二. 面向對象高級 2.1 static static叫做靜態&#xff0c;可以修飾成員變量、成員方法 2.1.1 static修飾成員變量 成員變量按照有無static修飾&#xff0c;分為兩種&#xff1a;類變量、實例變量&#xff08;對象…

JavaScript 語句語法的教程

JavaScript 是一種廣泛應用于網頁開發的腳本語言&#xff0c;熟練掌握 JavaScript 的語法是成為一名優秀的前端開發工程師的必備技能之一。本教程將詳細介紹 JavaScript 中的語句語法&#xff0c;幫助初學者快速入門并加深對 JavaScript 語法的理解。 一、注釋 在 JavaScript…

常見的爬蟲逆向面試題

文章轉載于&#xff1a;https://mp.weixin.qq.com/s/dXRo0D_Xx7E_h85XbnwPVQ 有興趣去源站瀏覽學習 主要自己看著方便些 1.HTTS三次握手 目前使用的 HTTP/HTTPS 協議是基于 TCP 協議之上的&#xff0c;因此也需要三次握手。在 TCP 三次握手建立鏈接之后&#xff0c;才會進行 …

故障診斷 | 一文解決,XGBoost極限梯度提升樹的故障診斷(Matlab)

效果一覽 文章概述 故障診斷 | 一文解決,XGBoost極限梯度提升樹的故障診斷(Matlab) 模型描述 XGBoost通過集成多個決策樹來建立一個強大的預測模型。它采用了一種特殊的梯度提升技術,稱為極限梯度提升(Extreme Gradient Boosting),以提高模型的性能和魯棒性。 極限梯度…

【大數據Hive】hive 多字段分隔符使用詳解

目錄 一、前言 二、hive默認分隔符規則以及限制 2.1 正常示例&#xff1a;單字節分隔符數據加載示例 2.2 特殊格式的文本數據&#xff0c;分隔符為特殊字符 2.2.1 文本數據的字段中包含了分隔符 三、突破默認限制規則約束 3.1 數據加載不匹配情況 1 3.2 數據加載不匹配…

python paramiko 網絡系統運維

概述 背景&#xff1a;網絡系統運維與建設&#xff1a;工作中發現客戶使用python腳本批量操作網絡設備導出多臺網絡設備的配置定期執行相關的巡檢工作 修改配置 # -*- coding:utf8 -*- """ # editor: hjjdreamer # create-time: 2024/3/3-23:31 # Python-Scri…