Java 8 新特性之 Lambda 表达式

Lambda 表达式是 Java 8 引入的一种新特性,用于简化匿名内部类的写法,支持函数式编程风格。它使代码更加简洁、可读性更强,尤其是在处理集合操作(如排序、过滤等)时非常有用。


一、Lambda 表达式的语法

Lambda 表达式的基本语法如下:

r 复制代码
(parameters) -> expression

ini 复制代码
(parameters) -> { statements; }

1. 参数部分

  • 参数可以有零个、一个或多个。
  • 如果只有一个参数且类型可以推断,则可以省略括号和类型声明。例如:
perl 复制代码
x -> x * x  // 等价于 (int x) -> { return x * x; }
  • 如果有多个参数,需要用括号包裹,并用逗号分隔。例如:
rust 复制代码
(x, y) -> x + y

2. 箭头符号 ​​->​

  • 箭头符号将参数列表与 Lambda 主体分隔开。

3. Lambda 主体

  • 如果主体是一个表达式,则不需要大括号 ​{}​​return​ 关键字。例如:
rust 复制代码
x -> x * x
  • 如果主体包含多条语句,则需要用大括号 ​{}​ 包裹,并显式使用 ​return​(如果需要返回值)。例如:
ini 复制代码
(x, y) -> {
    int result = x + y;
    return result;
}

二、Lambda 表达式的使用场景

Lambda 表达式主要用于实现函数式接口 (Functional Interface)。函数式接口是指只有一个抽象方法的接口。Java 8 提供了大量内置的函数式接口,也可以自定义。

1. 常见的内置函数式接口

接口名称 方法签名 描述
​Runnable​ ​void run()​ 不接受参数,也不返回结果
​Supplier<T>​ ​T get()​ 不接受参数,返回一个结果
​Consumer<T>​ ​void accept(T t)​ 接受一个参数,不返回结果
​Function<T, R>​ ​R apply(T t)​ 接受一个参数,返回一个结果
​Predicate<T>​ ​boolean test(T t)​ 接受一个参数,返回布尔值
​Comparator<T>​ ​int compare(T o1, T o2)​ 比较两个对象,返回整数

2. 使用示例

(1) Runnable 接口

传统方式:

csharp 复制代码
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello, World!");
    }
}).start();

使用 Lambda 表达式:

scss 复制代码
new Thread(() -> System.out.println("Hello, World!")).start();

(2) Comparator 接口

传统方式:

typescript 复制代码
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return s1.compareTo(s2);
    }
});

使用 Lambda 表达式:

scss 复制代码
Collections.sort(list, (s1, s2) -> s1.compareTo(s2));

或者更简洁地使用方法引用:

rust 复制代码
Collections.sort(list, String::compareTo);

(3) Function 接口

ini 复制代码
Function<Integer, Integer> square = x -> x * x;
System.out.println(square.apply(5));  // 输出 25

(4) Predicate 接口

ini 复制代码
Predicate<Integer> isEven = x -> x % 2 == 0;
System.out.println(isEven.test(4));  // 输出 true
System.out.println(isEven.test(5));  // 输出 false

三、Lambda 表达式的优势

  1. 代码简洁:减少了冗长的匿名内部类写法。
  2. 提高可读性:逻辑清晰,易于理解。
  3. 函数式编程支持:方便与流式 API(Stream API)结合使用。
  4. 延迟执行:Lambda 表达式通常与函数式接口一起使用,可以在需要时才执行逻辑。

四、Lambda 表达式与 Stream API 的结合

Java 8 引入了 Stream API,用于对集合进行高效的操作(如过滤、映射、排序等)。Lambda 表达式是 Stream API 的核心。

1. 示例:过滤和映射

假设有一个整数列表,我们想筛选出偶数并计算它们的平方:

ini 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

List<Integer> result = numbers.stream()
    .filter(n -> n % 2 == 0)  // 过滤偶数
    .map(n -> n * n)          // 计算平方
    .collect(Collectors.toList());

System.out.println(result);  // 输出 [4, 16, 36]

2. 示例:排序

对字符串列表按长度排序:

ini 复制代码
List<String> words = Arrays.asList("apple", "banana", "cherry");

words.sort((s1, s2) -> Integer.compare(s1.length(), s2.length()));

System.out.println(words);  // 输出 [apple, cherry, banana]

五、Lambda 表达式的限制

  1. 必须实现函数式接口:Lambda 表达式只能用于实现函数式接口,不能直接用于普通接口或类。
  2. 无法访问非 final 的局部变量 :Lambda 表达式中引用的外部局部变量必须是 ​final​ 或"有效 final"(即没有被重新赋值)。
ini 复制代码
int num = 10;  // 有效 final
Runnable r = () -> System.out.println(num);
num = 20;  // 编译错误,num 被重新赋值
  1. 不适合复杂逻辑:对于复杂的业务逻辑,仍然建议使用传统的匿名内部类或方法。

六、总结

Lambda 表达式是 Java 8 中非常重要的特性,它极大地简化了代码编写,特别是在集合操作和函数式编程中发挥着重要作用。通过结合 Stream API 和内置函数式接口,可以使代码更加简洁、灵活和高效。

然而,在使用 Lambda 表达式时需要注意其限制条件,确保代码的可维护性和可读性。

相关推荐
掘金者阿豪1 小时前
记一次NFS下的权限踩坑:从“Operation not permitted”到安装成功的折腾实录
后端
妙蛙种子3111 小时前
【Java设计模式 | 创建者模式】 原型模式
java·开发语言·后端·设计模式·原型模式
互联网散修1 小时前
零基础鸿蒙应用开发第三十四节:MVVM架构下的商品管理登录页
架构·harmonyos·mvvm·登录
Lyyaoo.1 小时前
【JAVA基础面经】线程的状态
java·开发语言
阿聪谈架构1 小时前
第07章(下):LangGraph 工作流进阶 —— 检查点、人工介入与多 Agent 协作
人工智能·后端
Hello小赵1 小时前
C语言如何自定义链接库——编译与调用
android·java·c语言
希望永不加班1 小时前
SpringBoot 配置绑定:@ConfigurationProperties
java·spring boot·后端·spring
悟空码字1 小时前
MySQL性能优化的天花板:10条你必须掌握的顶级SQL分析技巧
java·后端·mysql
indexsunny1 小时前
互联网大厂Java面试实战:Spring Boot、MyBatis与Kafka在电商场景中的应用
java·spring boot·面试·kafka·mybatis·电商·技术栈
Soofjan1 小时前
Go interface 源码:iface、itab、getitab 与动态派发
后端