Java Lambda 表达式与函数式接口知识点详解

一、Lambda 表达式概述

1. 定义与作用

  • Lambda 表达式是 Java 8 引入的新特性,是一种简洁的匿名函数书写方式,用于简化函数式接口的实现。
  • 作用:避免编写冗余的匿名内部类代码,提高代码简洁性和可读性,尤其适用于集合遍历、排序、线程任务等场景。

2. 语法结构

(参数列表) -> { 方法体 }
  • 参数列表:接口抽象方法的参数,可省略类型(由编译器推断),若只有一个参数可省略括号。
  • ->:Lambda 操作符,读作 “goes to”。
  • 方法体:若只有一条语句,可省略大括号和分号;若有返回值,可省略 return 关键字。

二、函数式接口(Functional Interface)

1. 定义

  • 仅包含一个抽象方法的接口(允许包含默认方法、静态方法和 Object 的公共方法)。
  • 必须使用 @FunctionalInterface 注解(非强制,但建议添加,用于编译器校验)。

2. 核心函数式接口

Java 8 在 java.util.function 包中提供了大量常用函数式接口,按参数和返回值分类如下:

(1)无参数无返回值:Runnable
// 传统匿名内部类
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello Runnable");
    }
}).start();

// Lambda 表达式
new Thread(() -> System.out.println("Hello Lambda")).start();
(2)单参数无返回值:Consumer<T>
  • 消费型接口,对参数进行处理(无返回值)。
Consumer<String> print = str -> System.out.println("Input: " + str);
print.accept("Lambda"); // 输出:Input: Lambda
(3)单参数有返回值:Function<T, R>
  • 函数型接口,将输入参数转换为另一种类型的结果。
Function<Integer, String> convert = num -> "Number: " + num;
String result = convert.apply(123); // 输出:Number: 123
(4)布尔型单参数:Predicate<T>
  • 断言型接口,用于条件判断,返回 boolean
Predicate<Integer> isEven = num -> num % 2 == 0;
System.out.println(isEven.test(4)); // 输出:true
(5)无参数有返回值:Supplier<T>
  • 供给型接口,用于生成指定类型的数据。
Supplier<Double> randomNum = () -> Math.random();
System.out.println(randomNum.get()); // 输出随机小数(如 0.345...)

三、Lambda 表达式的使用场景

1. 集合遍历(forEach

List<String> list = Arrays.asList("Apple", "Banana", "Cherry");
// 传统循环
for (String item : list) {
    System.out.print(item + " ");
}

// Lambda + forEach
list.forEach(item -> System.out.print(item + " ")); // 输出:Apple Banana Cherry 

2. 集合排序(sort

List<Integer> nums = Arrays.asList(3, 1, 4, 2);
// 传统 Comparator
nums.sort(new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2 - o1; // 降序
    }
});

// Lambda
nums.sort((a, b) -> b - a); // 等价于上述代码

3. 多线程任务(Runnable

// 传统方式
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Thread running");
    }
}).start();

// Lambda
new Thread(() -> System.out.println("Thread running")).start();

四、Lambda 表达式的变量捕获规则

1. 捕获外部变量

  • Lambda 表达式中可访问外层作用域的变量(包括成员变量和局部变量)。
  • 局部变量的要求:必须是事实不可变的(effectively final),即变量声明后不再修改。
int num = 10; // 未修改,符合规则
Consumer<String> consumer = str -> System.out.println(str + num); // 合法

num = 20; // 报错:Cannot assign a value to final variable 'num'

2. 与匿名内部类的区别

  • 匿名内部类:可修改外部局部变量(需声明为 final)。
  • Lambda 表达式:不允许修改外部局部变量,强制要求变量事实不可变,避免线程安全问题。

五、方法引用(Method Reference)

1. 定义

  • 是 Lambda 表达式的简化形式,用于引用已有的方法来替代 Lambda 体中的逻辑。
  • 语法:类名::方法名 或 对象::方法名

2. 常见类型

(1)静态方法引用(类名::静态方法
// Lambda:参数传递给静态方法
Function<Integer, String> func = num -> String.valueOf(num);
// 方法引用
Function<Integer, String> funcRef = String::valueOf;
(2)实例方法引用(对象::实例方法
String str = "Hello";
// Lambda:调用 str 的实例方法
Supplier<Integer> length = () -> str.length();
// 方法引用
Supplier<Integer> lengthRef = str::length;
(3)构造方法引用(类名::new
// Lambda:创建对象
Supplier<ArrayList> supplier = () -> new ArrayList();
// 方法引用
Supplier<ArrayList> supplierRef = ArrayList::new;

六、Lambda 表达式的优缺点

1. 优点

  • 代码简洁:减少冗余的样板代码,提升开发效率。
  • 函数式编程支持:便于使用集合流式操作(Stream API)和并行处理。
  • 可读性增强:逻辑聚焦,代码结构更清晰。

2. 缺点

  • 调试困难:无具体方法名,堆栈跟踪信息不友好。
  • 学习成本:对新手而言,函数式编程思想需要适应。
  • 滥用风险:过度使用可能导致代码逻辑晦涩难懂。

七、总结

  • Lambda 表达式是 Java 函数式编程的核心特性,通过简化函数式接口的实现,让代码更简洁优雅。
  • 函数式接口是 Lambda 表达式的载体,需牢记 @FunctionalInterface 注解的作用及常用接口(如 RunnableConsumerFunction 等)。
  • 方法引用是 Lambda 的进阶用法,进一步提升代码的简洁性和复用性。

合理运用 Lambda 表达式,能显著提升 Java 代码的表现力和开发效率,尤其在集合操作、多线程和流式处理中优势明显。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值