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.mzph.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 …