哈喽 大家好!
我是老陈,这节课一起来学习Lambda 表达式,Lambda就像 “匿名函数的速写本”,用极简语法替代冗长的匿名内部类,让代码像数学公式一样简洁! 核心思想是:将 “行为” 作为参数传递,用极简语法替代冗长代码。
39.1 Lambda 的核心特性:行为参数化与极简语法
Lambda 就像 “可传递的代码片段”,比如让线程执行一段代码时,无需定义完整的类,直接传递() -> System.out.println("Hello")这样的代码块,就像给机器人下达即时指令。
package com.lambda.demo;
import java.util.Arrays;
import java.util.Comparator;
/**
* @author 今日头条:老陈说编程
* Lambda表达式与匿名内部类的语法对比
* 展示Java中传统匿名内部类和Lambda表达式在实现函数式接口时的语法差异
*/
public class LambdaBasicFeatures {
public static void main(String[] args) {
// 1. 匿名内部类实现Runnable接口
// 创建一个实现Runnable接口的匿名类实例,重写run方法
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类线程");
}
}).start();
// 2. Lambda表达式实现Runnable接口(无参数、无返回值)
// 使用Lambda表达式简化语法,省略接口名和方法名,直接实现功能逻辑
new Thread(() -> System.out.println("Lambda线程")).start();
// 3. 匿名内部类实现Comparator接口
// 创建一个字符串数组用于排序演示
String[] names = {"张三", "李四", "王五"};
// 使用匿名内部类实现Comparator接口,按字符串长度比较
Arrays.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.length() - b.length(); // 升序排序
}
});
// 4. Lambda表达式实现Comparator接口(有参数、有返回值)
// 使用Lambda表达式进一步简化Comparator实现
// (a, b) -> a.length() - b.length() 等价于匿名内部类的完整实现
Arrays.sort(names, (a, b) -> a.length() - b.length());
System.out.println("排序结果:" + Arrays.toString(names)); // 输出按长度排序后的数组
}
}
39.2 核心语法:Lambda 表达式的五种形态
使用 Lambda 就像 “写数学表达式”—— 根据参数和返回值的不同,有五种简洁写法,从() -> {}到(a,b) -> a+b,每种形态都对应不同的业务场景。
package com.lambda.demo;
import java.util.function.*;
/**
* @author 今日头条:老陈说编程
* Lambda表达式五种语法形态综合演示
* 展示了从无参数到多参数,从无返回值到有返回值的Lambda表达式写法
*/
public class LambdaSyntax {
public static void main(String[] args) {
// 1. 无参数无返回值的Lambda表达式
// 实现Runnable接口,重写无参run()方法
Runnable r1 = () -> System.out.println("无参数Lambda");
// 2. 单参数无返回值的Lambda表达式
// 完整写法:显式指定参数类型和括号
Consumer<String> c1 = (String s) -> System.out.println(s.toUpperCase());
// 简化写法:省略参数类型和括号(单参数可省略括号)
Consumer<String> c2 = s -> System.out.println(s.toUpperCase());
// 3. 多参数无返回值的Lambda表达式
// 使用BiConsumer函数式接口,接收两个不同类型参数
// 使用代码块语法,可包含多条语句
BiConsumer<Integer, String> bc = (i, s) -> {
System.out.println(i + ": " + s);
};
// 4. 单参数有返回值的Lambda表达式
// 完整写法:显式指定参数类型为Integer
Function<Integer, Integer> f1 = (Integer x) -> x * x;
// 简化写法:省略参数类型、return关键字和花括号(单行表达式)
Function<Integer, Integer> f2 = x -> x * x;
// 5. 多参数有返回值的Lambda表达式
// 使用BinaryOperator函数式接口,接收两个同类型参数并返回同类型结果
// 显式指定参数类型为Double
BinaryOperator<Double> bo = (Double a, Double b) -> {
double result = a + b;
return result * 0.5;
};
// 调用示例:演示各个Lambda表达式的执行效果
r1.run(); // 执行无参Lambda
c2.accept("lambda"); // 处理字符串并转换为大写
bc.accept(1, "示例"); // 组合整数和字符串输出
System.out.println("计算结果:" + f2.apply(5)); // 计算平方值
System.out.println("计算结果:" + bo.apply(10.0, 20.0)); // 计算平均值
}
}
39.3 Lambda 与设计模式:函数式编程的架构实践
策略模式就像 "多功能计算器",不同计算策略是可更换的计算模块。Lambda 表达式则让这些模块的插拔变得像 "换电池" 一样简单!
package com.lambda.demo;
import java.util.function.Function;
/**
* @author 今日头条:老陈说编程
* Lambda简化策略模式(计算策略)
* 演示传统策略模式与Lambda表达式的结合使用
*/
public class LambdaStrategyPattern {
// 传统策略模式:定义计算策略接口
interface Calculator {
int calculate(int a, int b);
}
// 使用高阶函数的策略模式:通过Function接口实现双重参数传递
// 参数说明:
// - a, b:参与计算的两个整数
// - strategy:接收第一个参数并返回另一个Function的函数,第二个Function接收第二个参数并返回计算结果
static int compute(int a, int b, Function<Integer, Function<Integer, Integer>> strategy) {
return strategy.apply(a).apply(b);
}
public static void main(String[] args) {
// 1. 传统方式:创建匿名内部类实现策略接口
Calculator add = new Calculator() {
@Override
public int calculate(int a, int b) {
return a + b;
}
};
System.out.println("传统加法:" + add.calculate(5, 3)); // 输出: 8
// 2. Lambda方式:直接传递计算策略
// a -> b -> a + b 等价于:
// Function<Integer, Function<Integer, Integer>> addStrategy = a -> {
// return b -> a + b;
// };
int sum = compute(5, 3, a -> b -> a + b);
// Lambda乘法策略:直接传递乘法逻辑
int product = compute(5, 3, a -> b -> a * b);
System.out.println("Lambda加法:" + sum); // 输出: 8
System.out.println("Lambda乘法:" + product); // 输出: 15
// 3. 方法引用方式:使用Math类的subtractExact方法
int subtract = compute(5, 3, a -> b -> Math.subtractExact(a, b));
System.out.println("方法引用减法:" + subtract); // 输出: 2
}
}
39.4 与 Stream API 结合:Lambda 的最佳拍档
Lambda 与 Stream API 的组合就像 “数据处理的流水线”—— 用 Lambda 定义处理逻辑(如过滤、映射、排序),Stream 负责高效执行,让复杂的数据处理变得像写数学公式一样简洁。
package com.lambda.demo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author 今日头条:老陈说编程
* Lambda与Stream API结合实现复杂数据处理
* 演示传统集合处理方式与函数式流处理方式的对比
*/
public class LambdaStream {
public static void main(String[] args) {
// 初始化示例数据:包含姓名和年龄的字符串列表
List<String> names = Arrays.asList("张三,25", "李四,30", "王五,22", "赵六,35");
// 需求:筛选年龄>25的人,按年龄升序排列,获取姓名首字+年龄的字符串
// 传统方式:多层循环+条件判断
List<String> result1 = new ArrayList<>();
// 遍历每个元素并解析
for (String str : names) {
String[] arr = str.split(","); // 分割姓名和年龄
String name = arr[0];
int age = Integer.parseInt(arr[1]);
// 筛选年龄>25的记录
if (age > 25) {
// 格式化结果:姓名首字+年龄
result1.add(name.charAt(0) + "(" + age + ")");
}
}
// 手动提取年龄进行排序
Collections.sort(result1, (a, b) -> {
int ageA = Integer.parseInt(a.substring(a.indexOf('(') + 1, a.indexOf(')')));
int ageB = Integer.parseInt(b.substring(b.indexOf('(') + 1, b.indexOf(')')));
return ageA - ageB; // 升序排列
});
System.out.println("传统方式:" + result1); // [李(30), 赵(35)]
// Lambda+Stream方式:链式调用,代码更简洁
List<String> result2 = names.stream()
.map(s -> s.split(",")) // 将字符串分割为数组
.filter(arr -> Integer.parseInt(arr[1]) > 25) // 过滤年龄>25的元素
.map(arr -> arr[0].charAt(0) + "(" + arr[1] + ")") // 映射为格式化字符串
.sorted((a, b) -> { // 按年龄升序排序
int ageA = Integer.parseInt(a.substring(a.indexOf('(') + 1, a.indexOf(')')));
int ageB = Integer.parseInt(b.substring(b.indexOf('(') + 1, b.indexOf(')')));
return ageA - ageB;
})
.collect(Collectors.toList()); // 收集结果到列表
System.out.println("Lambda+Stream:" + result2); // [李(30), 赵(35)]
}
}