Java Lambda表達式指南

一、Lambda表達式基礎

1. 什么是Lambda表達式?

  • 匿名函數:沒有名稱的函數
  • 函數式編程:可作為參數傳遞的代碼塊
  • 簡潔語法:替代匿名內部類的更緊湊寫法

2. 基本語法

(parameters) -> expression
或
(parameters) -> { statements; }

3. 與傳統匿名類的對比

// 傳統方式
Runnable r1 = new Runnable() {@Overridepublic void run() {System.out.println("Hello World");}
};// Lambda方式
Runnable r2 = () -> System.out.println("Hello World");

二、函數式接口

1. 什么是函數式接口?

  • 單抽象方法接口:只有一個抽象方法的接口
  • 可用@FunctionalInterface注解標記

2. Java內置核心函數式接口

接口方法用途
Supplier<T>T get()無參返回結果
Consumer<T>void accept(T t)接收單個參數無返回
Function<T,R>R apply(T t)接收T類型返回R類型
Predicate<T>boolean test(T t)接收T返回布爾值
UnaryOperator<T>T apply(T t)一元操作(同類型轉換)
BiFunction<T,U,R>R apply(T t, U u)接收T,U返回R

3. 自定義函數式接口

@FunctionalInterface
interface StringProcessor {String process(String input);// 可以有默認方法default void info() {System.out.println("String processing interface");}
}StringProcessor toUpper = s -> s.toUpperCase();
System.out.println(toUpper.process("hello")); // 輸出: HELLO

三、Lambda使用場景

1. 集合遍歷

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 傳統方式
for (String name : names) {System.out.println(name);
}// Lambda方式
names.forEach(name -> System.out.println(name));// 方法引用方式
names.forEach(System.out::println);

2. 線程創建

// 傳統方式
new Thread(new Runnable() {@Overridepublic void run() {System.out.println("Running in thread");}
}).start();// Lambda方式
new Thread(() -> System.out.println("Running in thread")).start();

3. 條件過濾

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);// 過濾偶數
List<Integer> evens = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());

4. 排序

List<String> words = Arrays.asList("banana", "apple", "pear");// 傳統方式
Collections.sort(words, new Comparator<String>() {@Overridepublic int compare(String a, String b) {return a.compareTo(b);}
});// Lambda方式
Collections.sort(words, (a, b) -> a.compareTo(b));// 更簡潔的方式
words.sort(Comparator.naturalOrder());

四、方法引用

1. 四種方法引用類型

類型語法對應的Lambda
靜態方法ClassName::staticMethod(args) -> ClassName.staticMethod(args)
實例方法instance::method(args) -> instance.method(args)
任意對象的實例方法ClassName::method(obj, args) -> obj.method(args)
構造方法ClassName::new(args) -> new ClassName(args)

2. 使用示例

// 靜態方法引用
Function<String, Integer> parser = Integer::parseInt;// 實例方法引用
String str = "Hello";
Supplier<Integer> lengthSupplier = str::length;// 任意對象方法引用
Function<String, String> upperCase = String::toUpperCase;// 構造方法引用
Supplier<List<String>> listSupplier = ArrayList::new;

五、Stream API與Lambda

1. 流操作三階段

  1. 創建流:集合、數組等數據源
  2. 中間操作:過濾、映射等處理
  3. 終止操作:收集、遍歷等結果處理

2. 常用流操作

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");// 過濾并收集
List<String> longNames = names.stream().filter(name -> name.length() > 4).collect(Collectors.toList());// 映射轉換
List<Integer> nameLengths = names.stream().map(String::length).collect(Collectors.toList());// 排序
List<String> sorted = names.stream().sorted((a, b) -> b.compareTo(a)).collect(Collectors.toList());// 聚合操作
Optional<String> longest = names.stream().max(Comparator.comparingInt(String::length));

3. 并行流

long count = names.parallelStream().filter(name -> name.length() > 4).count();

六、Lambda高級特性

1. 變量捕獲

int threshold = 5; // 必須是final或事實上final
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);List<Integer> aboveThreshold = numbers.stream().filter(n -> n > threshold).collect(Collectors.toList());

2. 組合函數

Function<String, Integer> strToInt = Integer::parseInt;
Function<Integer, Integer> square = n -> n * n;Function<String, Integer> squareOfNumber = strToInt.andThen(square);
System.out.println(squareOfNumber.apply("5")); // 輸出: 25Predicate<String> isLong = s -> s.length() > 10;
Predicate<String> containsA = s -> s.contains("a");
Predicate<String> longAndContainsA = isLong.and(containsA);

3. 閉包示例

Function<Integer, Function<Integer, Integer>> adder = x -> y -> x + y;
Function<Integer, Integer> add5 = adder.apply(5);
System.out.println(add5.apply(3)); // 輸出: 8

七、異常處理

1. Lambda中的異常處理

List<String> numbers = Arrays.asList("1", "2", "three", "4");numbers.forEach(s -> {try {System.out.println(Integer.parseInt(s));} catch (NumberFormatException e) {System.out.println("Invalid number: " + s);}
});

2. 編寫可拋出異常的Lambda

@FunctionalInterface
interface ThrowingConsumer<T, E extends Exception> {void accept(T t) throws E;
}static <T> Consumer<T> wrap(ThrowingConsumer<T, Exception> consumer) {return t -> {try {consumer.accept(t);} catch (Exception e) {throw new RuntimeException(e);}};
}// 使用
List<String> files = Arrays.asList("file1.txt", "file2.txt");
files.forEach(wrap(file -> {// 可能拋出IOException的代碼Files.readAllLines(Paths.get(file)).forEach(System.out::println);
}));

八、實際應用案例

1. 事件處理

// Swing按鈕點擊事件
JButton button = new JButton("Click");
button.addActionListener(e -> System.out.println("Button clicked"));// JavaFX事件處理
Button fxButton = new Button("Click");
fxButton.setOnAction(event -> System.out.println("FX Button clicked"));

2. 緩存模式

public class Cache<K, V> {private final Map<K, V> map = new HashMap<>();private final Function<K, V> loader;public Cache(Function<K, V> loader) {this.loader = loader;}public V get(K key) {return map.computeIfAbsent(key, loader);}
}// 使用
Cache<String, BigDecimal> priceCache = new Cache<>(productId -> fetchPriceFromDatabase(productId));
BigDecimal price = priceCache.get("P1001");

3. 策略模式

interface PaymentStrategy {void pay(BigDecimal amount);
}class PaymentProcessor {private PaymentStrategy strategy;public void setStrategy(PaymentStrategy strategy) {this.strategy = strategy;}public void processPayment(BigDecimal amount) {strategy.pay(amount);}
}// 使用
PaymentProcessor processor = new PaymentProcessor();// 信用卡支付
processor.setStrategy(amount -> System.out.println("Paying " + amount + " via Credit Card"));
processor.processPayment(new BigDecimal("100.00"));// 支付寶支付
processor.setStrategy(amount -> System.out.println("Paying " + amount + " via Alipay"));
processor.processPayment(new BigDecimal("200.00"));

九、性能考慮

1. Lambda vs 匿名類

  • 初始化性能:Lambda首次調用稍慢,后續調用更快
  • 內存占用:Lambda通常占用更少內存
  • 最佳實踐:在熱點代碼中避免頻繁創建Lambda

2. 方法引用優化

// 較慢 - 每次創建新Lambda
list.stream().map(x -> x.toString()).collect(Collectors.toList());// 更快 - 使用方法引用
list.stream().map(Object::toString).collect(Collectors.toList());

3. 并行流注意事項

  • 數據量小(<1000元素)時順序流更快
  • 確保操作是無狀態的
  • 避免共享可變狀態

十、常見問題與陷阱

1. 變量修改

int sum = 0;
numbers.forEach(n -> {sum += n; // 編譯錯誤 - 不能修改捕獲的變量
});// 正確方式
int[] sumHolder = {0};
numbers.forEach(n -> sumHolder[0] += n);

2. this關鍵字

public class LambdaThis {private String value = "Enclosing";public void doWork() {Runnable r = () -> {System.out.println(this.value); // 輸出"Enclosing"};r.run();}
}

3. 重載問題

interface Adder {int add(int a, int b);
}interface SmartAdder {int add(double a, double b);
}class Calculator {void calculate(Adder adder) { /* ... */ }void calculate(SmartAdder adder) { /* ... */ }
}// 調用時會產生歧義
// calculator.calculate((x, y) -> x + y); // 編譯錯誤

十一、Java 8+ Lambda增強

1. Java 8 - 基本Lambda支持

  • 引入函數式接口
  • 方法引用
  • Stream API

2. Java 11 - 局部變量語法

var list = List.of("a", "b", "c");
list.forEach((var s) -> System.out.println(s));

3. Java 17 - 密封接口

sealed interface MathOperation permits Add, Subtract {int operate(int a, int b);
}final class Add implements MathOperation {public int operate(int a, int b) { return a + b; }
}final class Subtract implements MathOperation {public int operate(int a, int b) { return a - b; }
}// 使用
MathOperation add = (a, b) -> a + b;

十二、最佳實踐

  1. 保持簡潔:Lambda體最好不超過3行
  2. 使用方法引用:使代碼更清晰
  3. 避免副作用:純函數式操作更安全
  4. 命名參數:復雜Lambda應使用有意義的參數名
  5. 類型推斷:通常省略參數類型,必要時顯式聲明
  6. 文檔注釋:復雜Lambda應添加注釋說明

通過掌握Lambda表達式,您可以編寫出更簡潔、更易讀的Java代碼,特別是在處理集合和并發編程時。隨著函數式編程在Java中的不斷演進,Lambda已成為現代Java開發不可或缺的部分。

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

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

相關文章

面向對象設計中的類的分類:實體類、控制類和邊界類

目錄 前言1. 實體類&#xff08;Entity Class&#xff09;1.1 定義和作用1.2 實體類的特點1.3 實體類的示例 2. 控制類&#xff08;Control Class&#xff09;2.1 定義和作用2.2 控制類的特點2.3 控制類的示例 3. 邊界類&#xff08;Boundary Class&#xff09;3.1 定義和作用3…

C# 封裝教程

原文&#xff1a;C# 封裝_w3cschool &#xff08;注&#xff1a;本文為教程文章&#xff0c;請勿標記為付費文章&#xff01;特此聲明&#xff09; 封裝 被定義為"把一個或多個項目封閉在一個物理的或者邏輯的包中"。在面向對象程序設計方法論中&#xff0c;封裝是…

量化交易 - RSRS(阻力支撐相對強度)- 正確用法 - 年均收益18%

經過研究&#xff0c;發現RSRS的正確用法其實是需要用到兩個數據&#xff0c;分別是 n: 一階擬合樣本數&#xff0c;m:求均值方差樣本數&#xff0c;其中n比較小 如18&#xff0c;m比較大 如1100 經過調優后&#xff0c;收益率顯著上升&#xff01; 如下圖&#xff1a; &…

Oracle expdp的 EXCLUDE 參數詳解

Oracle expdp的 EXCLUDE 參數詳解 EXCLUDE 是 Oracle Data Pump Export (expdp) 工具中的一個關鍵參數&#xff0c;用于指定在導出過程中要排除的對象或對象類型。 一、基本語法 expdp username/password DUMPFILEexport.dmp DIRECTORYdpump_dir EXCLUDEobject_type[:name_c…

如何使用3DMAX插件PFSpliner將3D對象轉化為藝術樣條線?

什么是粒子流源(Particle Flow)是3DMAX的一個功能極其強大的粒子系統。它采用事件驅動模型,使用一個名為“粒子視圖”的特殊對話框。在“粒子視圖”中,您可以將描述粒子屬性(如形狀、速度、方向和一段時間內的旋轉)的單個運算符組合成稱為事件的組。每個操作符都提供一組…

【python】 循環語句(while)

1、循環語句 語法&#xff1a; while 條件:......... #只有條件為真時&#xff0c;才會執行while中的內容。 1.1循環語句基本使用 示例1&#xff1a; print("開始") while 1>2:print("人生得意須盡歡") print("結束") #輸出結果&#…

OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多變量時序預測一鍵對比

OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多變量時序預測一鍵對比 目錄 OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多變量時序預測一鍵對比預測效果基本介紹程序設計參考資料 預測效果 基本介紹 基于OOA-CN…

20250421在榮品的PRO-RK3566開發板的Android13下頻繁重啟RKNPU fde40000.npu: Adding to iommu gr

20250421在榮品的PRO-RK3566開發板的Android13下頻繁重啟RKNPU fde40000.npu: Adding to iommu gr 2025/4/21 14:50 緣起&#xff1a;電池沒電了&#xff0c;導致榮品的PRO-RK3566的核心板頻繁重啟。 內核時間4s就重啟。100%復現。 PRO-RK3566 Android13啟動到這里 復位&#…

動態監控進程

1.介紹: top和ps命令很相似,它們都是用來顯示正在執行的進程,top和ps最大的不同之處,在于top在執行中可以更新正在執行的進程. 2.基本語法&#xff1a; top [選項] 選項說明 ??僵死進程&#xff1a;內存沒有釋放,但是進程已經停止工作了,需要及時清理 交互操作說明 應用案…

657SJBH西藏藏藥特產銷售管理系統

畢業論文&#xff08;設計&#xff09;文獻綜述 西藏藏藥特產銷售管理系統的設計與實現 近年來&#xff0c;隨著網絡技術特別是Internet技術的普及和發展&#xff0c;電子商務的開發和應用成為一個熱門領域&#xff0c;在線藏藥特產銷售系統就是這其中的一員。 藏藥產業在西藏…

棧和隊列--數據結構初階(2)(C/C++)

文章目錄 前言理論部分棧的模擬實現STL中的棧容器隊列的模擬實現STL中的隊列容器 作業部分 前言 這期的話會給大家講解棧和隊列的模擬實現和在STL中棧和隊列怎么用的一些知識和習題部分(這部分側重于理論知識&#xff0c;習題倒還是不難) 理論部分 棧的模擬實現 typedef int…

RNN的理解

對于RNN的理解 import torch import torch.nn as nn import torch.nn.functional as F# 手動實現一個簡單的RNN class RNN(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(RNN, self).__init__()# 定義權重矩陣和偏置項self.hidden_size hidden…

二叉查找樹和B樹

二叉查找樹&#xff08;Binary Search Tree, BST&#xff09;和 B 樹&#xff08;B-tree&#xff09;都是用于組織和管理數據的數據結構&#xff0c;但它們在結構、應用場景和性能方面有顯著區別。 二叉查找樹&#xff08;Binary Search Tree, BST&#xff09; 特點&#xff1…

一段式端到端自動駕駛:VAD:Vectorized Scene Representation for Efficient Autonomous Driving

論文地址&#xff1a;https://github.com/hustvl/VAD 代碼地址&#xff1a;https://arxiv.org/pdf/2303.12077 1. 摘要 自動駕駛需要對周圍環境進行全面理解&#xff0c;以實現可靠的軌跡規劃。以往的方法依賴于密集的柵格化場景表示&#xff08;如&#xff1a;占據圖、語義…

OpenCV訓練題

一、創建一個 PyQt 應用程序&#xff0c;該應用程序能夠&#xff1a; 使用 OpenCV 加載一張圖像。在 PyQt 的窗口中顯示這張圖像。提供四個按鈕&#xff08;QPushButton&#xff09;&#xff1a; 一個用于將圖像轉換為灰度圖一個用于將圖像恢復為原始彩色圖一個用于將圖像進行…

opencv函數展示4

一、形態學操作函數 1.基本形態學操作 &#xff08;1&#xff09;cv2.getStructuringElement() &#xff08;2&#xff09;cv2.erode() &#xff08;3&#xff09;cv2.dilate() 2.高級形態學操作 &#xff08;1&#xff09;cv2.morphologyEx() 二、直方圖處理函數 1.直方圖…

iPhone 13P 換超容電池,一年實記的“電池循環次數-容量“柱狀圖

繼上一篇 iPhone 13P 更換"移植電芯"和"超容電池"&#x1f50b;體驗&#xff0c;詳細記錄了如何更換這兩種電池&#xff0c;以及各自的優略勢對比。 一晃一年過去&#xff0c;時間真快&#xff0c;這次分享下記錄了使用超容電池的 “循環次數 - 容量(mAh)…

基于 pnpm + Monorepo + Turbo + 無界微前端 + Vite 的企業級前端工程實踐

基于 pnpm Monorepo Turbo 無界微前端 Vite 的企業級前端工程實踐 一、技術演進&#xff1a;為什么引入 Vite&#xff1f; 在微前端與 Monorepo 架構落地后&#xff0c;構建性能成為新的優化重點&#xff1a; Webpack 構建瓶頸&#xff1a;復雜配置導致開發啟動慢&#…

(五)機器學習---決策樹和隨機森林

在分類問題中還有一個常用算法&#xff1a;就是決策樹。本文將會對決策樹和隨機森林進行介紹。 目錄 一.決策樹的基本原理 &#xff08;1&#xff09;決策樹 &#xff08;2&#xff09;決策樹的構建過程 &#xff08;3&#xff09;決策樹特征選擇 &#xff08;4&#xff0…

Vue3使用AntvG6寫拓撲圖,可添加修改刪除節點和邊

npm安裝antv/g6 npm install antv/g6 --save 上代碼 <template><div id"tpt1" ref"container" style"width: 100%;height: 100%;"></div> </template><script setup>import { Renderer as SVGRenderer } from …