最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java中的Lambda表達式使用及說明

 更新時間:2026年05月16日 10:21:50   作者:heartbeat..  
文章介紹了Java?8中Lambda表達式的基本概念及其在Stream流操作中的應(yīng)用,Lambda表達式簡化了函數(shù)式接口的實現(xiàn),與Stream結(jié)合使用更流暢,文章還提供了Lambda表達式的各種簡化技巧和注意事項,如方法引用、變量捕獲規(guī)則以及異常處理等

一、介紹:Stream的“黃金搭檔”

 Lambda 表達式是 Java 8 引入的 函數(shù)式編程語法糖,核心作用是 簡化函數(shù)式接口的實現(xiàn)代碼(替代冗余的匿名內(nèi)部類),也是 Stream 流式操作的 “黃金搭檔”—— 沒有 Lambda,Stream 的鏈式調(diào)用會變得臃腫難讀。

二、先搞懂:Lambda 只為 “函數(shù)式接口” 服務(wù)

Lambda 表達式不能單獨使用,它的唯一用途是 快速實現(xiàn) “函數(shù)式接口”

  • 函數(shù)式接口:只有 一個抽象方法 的接口(可以有默認方法、靜態(tài)方法);
  • 常見的函數(shù)式接口:Predicate(判斷條件)、Function(數(shù)據(jù)轉(zhuǎn)換)、Consumer(消費數(shù)據(jù))、Runnable(無參無返回)等(Stream 操作的參數(shù)全是這類接口)。

舉個對比:用匿名內(nèi)部類 vs Lambda 實現(xiàn) Runnable(線程任務(wù))

// 1. 傳統(tǒng)匿名內(nèi)部類(冗余)
new Thread(new Runnable() {
    @Override
    public void run() { // 唯一抽象方法
        System.out.println("匿名內(nèi)部類執(zhí)行線程任務(wù)");
    }
}).start();

// 2. Lambda 表達式(簡潔)
new Thread(() -> System.out.println("Lambda 執(zhí)行線程任務(wù)")).start();

Lambda 自動 “對接” 函數(shù)式接口的唯一抽象方法,省去了 new 接口()@Override、方法名等冗余代碼。

舉個簡單的例子:

假設(shè)你要給朋友寄一本書(對應(yīng) “一段核心邏輯”):

匿名內(nèi)部類

就像把書放進一個完整的快遞箱 —— 要選箱子(定義匿名類)、填快遞單(實現(xiàn)接口方法)、封箱(寫方法體),哪怕箱子比書還大(冗余代碼比核心邏輯多),也必須按流程來。比如用 Comparator 排序:

// 匿名內(nèi)部類:“完整快遞箱”,冗余代碼多
List<Integer> list = Arrays.asList(3,1,2);
Collections.sort(list, new Comparator<Integer>() {
    @Override
    public int compare(Integer a, Integer b) {
        return a - b; // 核心邏輯:“書”
    }
});

Lambda 表達式

就像 “裸奔快遞”—— 直接把書交給快遞員,不用箱子、不用填復(fù)雜快遞單,只說 “送到 XX 地址”(核心邏輯)。多余的 “包裝”(類定義、方法聲明)全省略,直奔主題。同樣的排序邏輯,Lambda 簡化后:

// Lambda:“裸奔快遞”,只留核心邏輯
list.sort((a, b) -> a - b);

匿名內(nèi)部類是 “裹腳布式代碼”,Lambda 是 “緊身衣式代碼”—— 去掉所有不必要的冗余,只保留核心邏輯,讓代碼從 “臃腫” 變 “精干”。

傳遞行為:把 “做事的方法” 當 “快遞包裹” 傳遞(函數(shù)式接口的核心)

生活中,你可以把 “做飯” 這個行為(不是做好的飯)告訴別人:比如讓媽媽 “按我的方法做飯”(傳遞行為),而不是自己先做好飯再交給媽媽(傳遞結(jié)果)。

Lambda 就是 “傳遞行為” 的代碼版 —— 它不直接執(zhí)行邏輯,而是把 “邏輯本身” 當作參數(shù)傳給方法,讓方法按需執(zhí)行。

舉例:用 Stream 過濾列表(傳遞 “過濾規(guī)則” 這個行為):

List<String> fruits = Arrays.asList("蘋果", "香蕉", "橙子", "小番茄");
// 傳遞“長度>2”這個行為給 filter 方法
List<String> longFruits = fruits.stream()
                               .filter(f -> f.length() > 2) // Lambda:傳遞“過濾行為”
                               .collect(Collectors.toList());

普通代碼是 “傳遞結(jié)果”(比如先過濾好列表再傳入方法),Lambda 是 “傳遞菜譜”(告訴方法 “怎么過濾”,讓方法自己執(zhí)行)—— 靈活度拉滿,同一個方法(如 filter)可以接收不同 “行為” 實現(xiàn)不同功能(過濾長度 > 2、過濾包含 “果” 字等)。

方法引用是 “快遞的‘加急件’”

如果 Lambda 里的邏輯只是 “直接調(diào)用某個已有的方法”(沒有額外加工),就像快遞是 “直接轉(zhuǎn)寄”(不用拆包、不用額外處理),這時可以用方法引用進一步簡化 —— 相當于給快遞貼了 “加急標簽”,跳過中間冗余的 “Lambda 語法糖”,直接指向目標方法。

  • Lambda 寫法:就像轉(zhuǎn)寄快遞時,你還要跟快遞員說 “把這個包裹交給 XX”(多余的 “口頭指示”);
  • 方法引用寫法:直接在包裹上寫 “收件人:XX”,快遞員直接送達,不用你多廢話。

舉例:按字符串長度排序:

// Lambda 寫法:“口頭指示”快遞員
list.sort((s1, s2) -> s1.length() - s2.length());

// 方法引用寫法:“直接寫收件人”,更簡潔
list.sort(Comparator.comparingInt(String::length));

Lambda 捕獲的變量是 “快遞單上的固定信息”—— 一旦下單(定義 Lambda),信息就不能改了,否則快遞員(JVM)不知道該按哪個信息執(zhí)行。

異常處理:不能 “藏著掖著” 未聲明的 checked 異常

就像寄快遞時不能隱瞞 “易碎品”(否則損壞不賠),Lambda 里如果拋出 checked 異常(如 IOException),必須明確處理(try-catch)或讓包含它的方法聲明拋出 —— 不能偷偷拋出,否則編譯器會 “拒收”。

// 錯誤:未處理 checked 異常
List<File> files = Arrays.asList(new File("a.txt"), new File("b.txt"));
files.stream().map(file -> file.getCanonicalPath()); // getCanonicalPath 拋出 IOException

// 正確:要么 try-catch,要么聲明異常
files.stream().map(file -> {
    try {
        return file.getCanonicalPath();
    } catch (IOException e) {
        throw new RuntimeException(e); // 轉(zhuǎn)為 unchecked 異常
    }
});

Lambda 里的 checked 異常是 “快遞里的易碎品”—— 必須提前告訴 “快遞員”(編譯器)怎么處理(try-catch),否則 “快遞”(代碼)無法正常投遞(編譯報錯)。

三、Lambda 核心語法:(參數(shù)) -> 代碼塊

語法格式:(參數(shù)列表) -> { 業(yè)務(wù)代碼 },有 3 個關(guān)鍵部分:

部分說明
(參數(shù)列表)對應(yīng)函數(shù)式接口抽象方法的參數(shù)(可省略參數(shù)類型,單參數(shù)可省略括號)
->箭頭運算符,分隔參數(shù)和代碼塊(固定寫法)
{ 代碼塊 }對應(yīng)抽象方法的實現(xiàn)邏輯(單條語句可省略大括號,有返回值時可省略 return)

語法簡化規(guī)則(越用越簡潔)

  1. 省略參數(shù)類型:Java 能通過接口自動推斷參數(shù)類型;
  2. 單參數(shù)省略括號:只有 1 個參數(shù)時,(a) 可簡化為 a;
  3. 單語句省略大括號:代碼塊只有 1 行時,{ ... } 可省略;
  4. 單返回語句省略 return:若代碼塊是返回語句,省略大括號的同時可省略 return。

語法示例(以Comparator接口為例,用于排序)

// 原始 Lambda(無簡化)
Comparator<Integer> comp1 = (Integer a, Integer b) -> {
    return b - a; // 降序排序
};

// 簡化1:省略參數(shù)類型(Java 自動推斷)
Comparator<Integer> comp2 = (a, b) -> {
    return b - a;
};

// 簡化2:單返回語句省略大括號和 return
Comparator<Integer> comp3 = (a, b) -> b - a;

// 最終簡化結(jié)果(Stream 中直接使用)
List<Integer> list = Arrays.asList(3,1,2);
list.stream().sorted((a, b) -> b - a).forEach(System.out::println); // 輸出 3,2,1

四、Lambda 與 Stream 的 “天作之合”

Stream 的中間操作(filter、map 等)和終端操作(forEachsorted 等),參數(shù)全是函數(shù)式接口 ——Lambda 剛好能簡化這些接口的實現(xiàn),讓 Stream 鏈式調(diào)用更流暢。

Stream

常見操作

函數(shù)式接口接口抽象方法Lambda 示例(實現(xiàn)邏輯)
filter()Predicate<T>boolean test(T t)emp -> emp.getAge() >= 30(篩選 30 歲以上員工)
map()Function<T,R>R apply(T t)emp -> emp.getSalary()(提取員工工資)
forEach()Consumer<T>void accept(T t)System.out::println(打印元素,方法引用簡化)
sorted()Comparator<T>int compare(T a,T b)(a,b) -> b - a(降序排序)
findAny()Predicate<T>boolean test(T t)n -> n % 2 == 0(找任意偶數(shù))

示例:

List<Employee> empList = Arrays.asList(
    new Employee("張三", 28, 15000),
    new Employee("李四", 32, 18000),
    new Employee("趙六", 35, 20000)
);

// 需求:篩選30歲以上員工 → 提取姓名 → 按姓名長度降序 → 打印
empList.stream()
    .filter(emp -> emp.getAge() >= 30) // Predicate:篩選條件
    .map(Employee::getName) // Function:提取姓名(方法引用簡化Lambda)
    .sorted((name1, name2) -> name2.length() - name1.length()) // Comparator:排序
    .forEach(System.out::println); // Consumer:打印

// 輸出:趙六(2字)、李四(2字)(若有3字姓名會排在前面)

五、Lambda 簡化技巧:方法引用(::)

當 Lambda 的代碼塊只是 調(diào)用一個已存在的方法(無額外邏輯),可以用 類名::方法名 或 對象::方法名 進一步簡化,這就是 方法引用。

方法引用類型語法格式Lambda 等效寫法示例(Stream 中)
靜態(tài)方法引用類名::靜態(tài)方法(a,b) -> 類名.靜態(tài)方法(a,b)Integer::compare → (a,b) -> Integer.compare(a,b)
實例方法引用(對象)對象::實例方法(x) -> 對象.實例方法(x)System.out::println → (s) -> System.out.println(s)
實例方法引用(參數(shù))類名::實例方法(a,b) -> a.實例方法(b)String::equals → (s1,s2) -> s1.equals(s2)
構(gòu)造器引用類名::new(參數(shù)) -> new 類名(參數(shù))ArrayList::new → () -> new ArrayList<>()

示例:

// 1. 實例方法引用(對象):System.out::println 替代 (s) -> System.out.println(s)
List<String> names = Arrays.asList("張三", "李四");
names.stream().forEach(System.out::println);

// 2. 實例方法引用(參數(shù)):String::length 替代 (s) -> s.length()
List<Integer> nameLengths = names.stream()
    .map(String::length) // 提取姓名長度
    .collect(Collectors.toList());

// 3. 構(gòu)造器引用:ArrayList::new 替代 () -> new ArrayList<>()
List<String> newNames = names.stream()
    .filter(name -> name.length() == 2)
    .collect(Collectors.toCollection(ArrayList::new));

六、Lambda 中的變量捕獲

Lambda 可以訪問外部變量,但有嚴格限制:

  1. 只能訪問 final 或 effectively final 的變量(即變量聲明后不再修改);
  2. 不能修改外部變量(否則編譯報錯)。

示例:

// 正確:外部變量是 effectively final(聲明后未修改)
int minAge = 30;
empList.stream().filter(emp -> emp.getAge() >= minAge).forEach(System.out::println);

// 錯誤:修改外部變量(編譯報錯)
int count = 0;
empList.stream().forEach(emp -> {
    count++; // 報錯:Variable used in lambda expression should be final or effectively final
});

原因:Lambda 本質(zhì)是匿名函數(shù),可能在多線程中執(zhí)行,禁止修改外部變量是為了避免線程安全問題。

七、Lambda 常見誤區(qū)

  1. 誤以為能替代所有匿名內(nèi)部類:只有 “函數(shù)式接口”(單抽象方法)才能用 Lambda,多抽象方法的接口不行;
  2. 修改外部變量:違反 “final 或 effectively final” 規(guī)則,編譯報錯;
  3. 過度簡化導(dǎo)致可讀性下降:復(fù)雜邏輯(多行業(yè)務(wù)代碼)不適合用 Lambda,建議拆分為普通方法,再用方法引用調(diào)用;
  4. 忽略異常處理:Lambda 中拋出受檢異常(如 IOException),需在代碼塊中捕獲,或函數(shù)式接口的抽象方法聲明該異常。

示例:

// 錯誤:Lambda 中拋出受檢異常,未處理
List<String> files = Arrays.asList("a.txt", "b.txt");
files.stream().map(file -> new FileInputStream(file)); // 編譯報錯:未處理 IOException

// 正確:捕獲異常
files.stream().map(file -> {
    try {
        return new FileInputStream(file);
    } catch (IOException e) {
        throw new RuntimeException(e); // 轉(zhuǎn)為運行時異常拋出
    }
});

八、總結(jié)

Lambda 表達式的核心價值是 “簡化代碼 + 傳遞行為”

  1. 專為函數(shù)式接口設(shè)計,替代冗余的匿名內(nèi)部類;
  2. 語法簡潔靈活,配合 Stream 能大幅提升代碼可讀性和開發(fā)效率;
  3. 方法引用是 Lambda 的 “進階簡化技巧”,適合簡單的方法調(diào)用場景;
  4. 注意變量捕獲規(guī)則和異常處理,避免踩坑。

一句話記住 Lambda:“少寫代碼,多傳邏輯”—— 它讓 Java 從 “面向?qū)ο?rdquo; 向 “函數(shù)式編程” 邁出了重要一步,而 Stream 則是 Lambda 最經(jīng)典的應(yīng)用場景。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot SSE服務(wù)端主動推送事件的實現(xiàn)

    SpringBoot SSE服務(wù)端主動推送事件的實現(xiàn)

    本文主要介紹了SpringBoot SSE服務(wù)端主動推送事件的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • 圖文詳解JAVA實現(xiàn)哈夫曼樹

    圖文詳解JAVA實現(xiàn)哈夫曼樹

    所謂哈夫曼樹就是要求最小加權(quán)路徑長度,這是什么意思呢?簡而言之,就是要所有的節(jié)點對應(yīng)的路徑長度(高度-1)乘以該節(jié)點的權(quán)值,然后保證這些結(jié)果之和最小。下面這篇文章就給大家詳細介紹
    2016-08-08
  • SpringBoot整合Mybatis Plus多數(shù)據(jù)源的實現(xiàn)示例

    SpringBoot整合Mybatis Plus多數(shù)據(jù)源的實現(xiàn)示例

    本文主要介紹了SpringBoot整合Mybatis Plus多數(shù)據(jù)源的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 詳解FutureTask如何實現(xiàn)最大等待時間

    詳解FutureTask如何實現(xiàn)最大等待時間

    這篇文章主要為大家詳細介紹了如何從源碼中了解FutureTask實現(xiàn)最大等待時間的方法,文中的示例代碼講解詳細,感興趣的可以了解一下
    2023-03-03
  • IDEA 2023創(chuàng)建JSP項目的完整步驟教程

    IDEA 2023創(chuàng)建JSP項目的完整步驟教程

    這篇文章主要介紹了IDEA 2023創(chuàng)建JSP項目的完整步驟教程,創(chuàng)建項目需要經(jīng)過新建項目、設(shè)置項目名稱和路徑、選擇JDK版本、添加模塊和工件、配置Tomcat服務(wù)器等步驟,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2024-10-10
  • Spring??AOP的兩種使用方法

    Spring??AOP的兩種使用方法

    這篇文章主要介紹了Spring?AOP的兩種使用方法,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • Maven與Gradle的區(qū)別對比分析

    Maven與Gradle的區(qū)別對比分析

    這篇文章給大家給大家介紹了Maven與Gradle的區(qū)別對比分析,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2026-05-05
  • 解決json串和實體類字段不一致的問題

    解決json串和實體類字段不一致的問題

    這篇文章主要介紹了解決json串和實體類字段不一致的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • SpringCloud微服務(wù)架構(gòu)升級匯總

    SpringCloud微服務(wù)架構(gòu)升級匯總

    這篇文章主要介紹了SpringCloud微服務(wù)架構(gòu)升級匯總,它提倡將單一應(yīng)用程序劃分成一組小的服務(wù),服務(wù)之間互相協(xié)調(diào)、互相配合,為用戶提供最終價值,需要的朋友可以參考下
    2019-06-06
  • 使用Mybatis Plus整合多數(shù)據(jù)源和讀寫分離的詳細過程

    使用Mybatis Plus整合多數(shù)據(jù)源和讀寫分離的詳細過程

    這篇文章主要介紹了Mybatis Plus整合多數(shù)據(jù)源和讀寫分離的詳細過程,mybatisplus可以整合阿里的分布式事務(wù)組件seata,本文通過示例代碼給大家介紹的非常詳細,需要的朋友參考下吧
    2021-09-09

最新評論

政和县| 册亨县| 清水河县| 陆川县| 紫阳县| 固阳县| 洪洞县| 廊坊市| 莱西市| 抚州市| 盐亭县| 平顶山市| 镇安县| 湖南省| 山东省| 平潭县| 乌拉特中旗| 喜德县| 竹溪县| 阜新市| 汉沽区| 习水县| 武夷山市| 泾源县| 常德市| 高淳县| 永仁县| 双柏县| 汝南县| 玛纳斯县| 盐津县| 肇州县| 独山县| 万全县| 当阳市| 昂仁县| 大冶市| 贵州省| 乌恰县| 宁阳县| 黎平县|