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

java中的Lambda表達(dá)式使用及說(shuō)明

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

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

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

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

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

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

舉個(gè)對(duì)比:用匿名內(nèi)部類 vs Lambda 實(shí)現(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 表達(dá)式(簡(jiǎn)潔)
new Thread(() -> System.out.println("Lambda 執(zhí)行線程任務(wù)")).start();

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

舉個(gè)簡(jiǎn)單的例子:

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

匿名內(nèi)部類

就像把書放進(jìn)一個(gè)完整的快遞箱 —— 要選箱子(定義匿名類)、填快遞單(實(shí)現(xiàn)接口方法)、封箱(寫方法體),哪怕箱子比書還大(冗余代碼比核心邏輯多),也必須按流程來(lái)。比如用 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 表達(dá)式

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

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

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

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

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

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

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

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

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

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

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

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

舉例:按字符串長(zhǎng)度排序:

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

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

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

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

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

// 錯(cuò)誤:未處理 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),否則 “快遞”(代碼)無(wú)法正常投遞(編譯報(bào)錯(cuò))。

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

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

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

語(yǔ)法簡(jiǎn)化規(guī)則(越用越簡(jiǎn)潔)

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

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

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

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

// 簡(jiǎn)化2:?jiǎn)畏祷卣Z(yǔ)句省略大括號(hào)和 return
Comparator<Integer> comp3 = (a, b) -> b - a;

// 最終簡(jiǎn)化結(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 剛好能簡(jiǎn)化這些接口的實(shí)現(xiàn),讓 Stream 鏈?zhǔn)秸{(diào)用更流暢。

Stream

常見操作

函數(shù)式接口接口抽象方法Lambda 示例(實(shí)現(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(打印元素,方法引用簡(jiǎn)化)
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歲以上員工 → 提取姓名 → 按姓名長(zhǎng)度降序 → 打印
empList.stream()
    .filter(emp -> emp.getAge() >= 30) // Predicate:篩選條件
    .map(Employee::getName) // Function:提取姓名(方法引用簡(jiǎn)化Lambda)
    .sorted((name1, name2) -> name2.length() - name1.length()) // Comparator:排序
    .forEach(System.out::println); // Consumer:打印

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

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

當(dāng) Lambda 的代碼塊只是 調(diào)用一個(gè)已存在的方法(無(wú)額外邏輯),可以用 類名::方法名 或 對(duì)象::方法名 進(jìn)一步簡(jiǎn)化,這就是 方法引用。

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

示例:

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

// 2. 實(shí)例方法引用(參數(shù)):String::length 替代 (s) -> s.length()
List<Integer> nameLengths = names.stream()
    .map(String::length) // 提取姓名長(zhǎng)度
    .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 可以訪問外部變量,但有嚴(yán)格限制:

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

示例:

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

// 錯(cuò)誤:修改外部變量(編譯報(bào)錯(cuò))
int count = 0;
empList.stream().forEach(emp -> {
    count++; // 報(bào)錯(cuò):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ī)則,編譯報(bào)錯(cuò);
  3. 過度簡(jiǎn)化導(dǎo)致可讀性下降:復(fù)雜邏輯(多行業(yè)務(wù)代碼)不適合用 Lambda,建議拆分為普通方法,再用方法引用調(diào)用;
  4. 忽略異常處理:Lambda 中拋出受檢異常(如 IOException),需在代碼塊中捕獲,或函數(shù)式接口的抽象方法聲明該異常。

示例:

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

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

八、總結(jié)

Lambda 表達(dá)式的核心價(jià)值是 “簡(jiǎn)化代碼 + 傳遞行為”

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

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

    Spring??AOP的兩種使用方法

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

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

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

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

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

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

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

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

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

最新評(píng)論

库伦旗| 宿松县| 环江| 九寨沟县| 延津县| 县级市| 牟定县| 迁西县| 五家渠市| 英超| 都兰县| 织金县| 蕉岭县| 永定县| 澳门| 隆尧县| 保亭| 万源市| 方城县| 石家庄市| 英吉沙县| 焦作市| 宣武区| 潜江市| 秦皇岛市| 宝兴县| 长泰县| 高雄县| 永安市| 西和县| 吉安县| 咸阳市| 建湖县| 城口县| 历史| 遂溪县| 皋兰县| 凭祥市| 社会| 张家港市| 浦县|