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

相关推荐
青云交38 分钟前
Java 大视界 -- 基于 Java 的大数据实时流处理在智能电网分布式电源接入与电力系统稳定性维护中的应用(404)
java·大数据·分布式·智能电网·flink 实时流处理·kafka 数据采集·iec 61850 协议
fured1 小时前
[调试][实现][原理]用Golang实现建议断点调试器
开发语言·后端·golang
仰望星空@脚踏实地1 小时前
maven scope 详解
java·maven·scope
bobz9651 小时前
linux cpu CFS 调度器有使用 令牌桶么?
后端
bobz9652 小时前
linux CGROUP CPU 限制有使用令牌桶么?
后端
M_Reus_112 小时前
Groovy集合常用简洁语法
java·开发语言·windows
带刺的坐椅2 小时前
10分钟带你体验 Solon 的状态机
java·solon·状态机·statemachine
小鹅叻2 小时前
MyBatis题
java·tomcat·mybatis
RainbowSea2 小时前
4. LangChain4j 模型参数配置超详细说明
java·langchain·ai编程
RainbowSea2 小时前
3. LangChain4j + 低阶 和 高阶 API的详细说明
java·llm·ai编程