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

相关推荐
天空属于哈夫克34 天前
企业微信二次开发:精准实现关键词自动回复
架构·企业微信
子兮曰4 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
小羊没烦恼!4 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
子兮曰4 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
俊昭喜喜里4 天前
java中的继承和多态的区别
java
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
爱勇宝4 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
譕痕4 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码4 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖4 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商