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 分钟前
常用排序方法
java·开发语言·算法
青云交4 分钟前
Java 大视界 -- 基于 Java 的大数据实时流处理在工业物联网设备故障预测与智能运维中的应用(384)
java·大数据·物联网·flink·设备故障预测·智能运维·实时流处理
半桔15 分钟前
【STL源码剖析】从源码看 vector:底层扩容逻辑与内存复用机制
java·开发语言·c++·容器·stl
洛卡卡了26 分钟前
面试官问限流降级,我项目根本没做过,咋办?
后端·面试·架构
慕y27427 分钟前
Java学习第一百零九部分——Jenkins(一)
java·学习·jenkins
ezl1fe1 小时前
RAG 每日一技(十四):化繁为简,统揽全局——用LangChain构建高级RAG流程
人工智能·后端·算法
悟能不能悟1 小时前
cdn是什么
java
amazingCompass1 小时前
Java 开发必备技能:深入理解与实战 IntelliJ IDEA 中的 VM Options
后端
爱科研的瞌睡虫1 小时前
C++线程中 detach() 和 join() 的区别
java·c++·算法
每天的每一天1 小时前
分布式文件系统05-生产级中间件的Java网络通信技术深度优化
java·开发语言·中间件