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 表达式时需要注意其限制条件,确保代码的可维护性和可读性。

相关推荐
树獭叔叔3 分钟前
GRPO:比PPO更简单的RLHF算法
后端·aigc·openai
shelter4 分钟前
并发操作session对象导致登录闪退问题
后端
兆子龙14 分钟前
TypeScript高级类型编程:从入门到精通
前端·后端
IT_陈寒23 分钟前
Python开发者的效率革命:这5个技巧让你的代码提速50%!
前端·人工智能·后端
MekoLi2938 分钟前
Spring AI 与 LangChain4j 从入门到精通:Java 后端开发者的 AI 实战手册
后端·面试
我真会写代码38 分钟前
深度解析并发编程锁升级:从偏向锁到重量级锁,底层原理+面试考点全拆解
java·并发编程·
guoji778840 分钟前
2026年Gemini 3 Pro vs 豆包2.0深度评测:海外顶流与国产黑马谁更强?
大数据·人工智能·架构
树獭叔叔42 分钟前
从RLHF到PPO:让AI学会说人话
后端·aigc·openai
Meepo_haha44 分钟前
创建Spring Initializr项目
java·后端·spring
会编程的土豆44 分钟前
C++中的 lower_bound 和 upper_bound:一篇讲清楚
java·数据结构·算法