Java Lambda表达式, Lambda Expressions in Java
Lambda表达式
在Java编程的世界中,Lambda表达式是Java 8中引入的一个重要的新特性。它们提供了一种简洁的方式来表示匿名函数,即没有名称的函数。
Lambda表达式有助于编写更具可读性和可维护性的代码,特别是在处理函数式接口时。
Java8之前,写匿名类非常繁琐,代码冗长,引入Lambda表达式和函数式接口,让Java代码更加简洁。
Lambda表达式是JDK8中引入的语法糖,用于简化匿名类实现函数式接口的代码,写起来简单又高效。
Lambda是一种简洁的语法形式,用于表示匿名函数,没有方法名,没有修饰符
(parameters) -> { body }
参数、箭头、方法体。参数可以省略类型,方法体则是要执行的代码。
函数式接口
函数式接口是只包含一个抽象方法的接口,通常使用**@FunctionalInterface**注解标识。
- 核心特点:只能有一个抽象方法
- 作用:作为Lambda表达式的类型
Lambda表达式本质上是对函数式接口的实现。
三大对应关系
- 方法签名对应:Lambda表达式的参数列表、返回类型必须与接口的唯一抽象方法相匹配
- 类型自动推断:编译器通过上下文(赋值目标的类型)自动推断Lambda参数和返回值的类型,无需显式声明
- 运行时实现:Lambda表达式在编译阶段被转换成函数式接口的具体实现,实现了接口方法
使用场景:函数式接口主要用于函数式编程、流操作(Stream API)、事件处理等场景,Lambda表达式使这些操作的代码更加简洁优雅
如何用Lambda表达式实现匿名函数
JDK8之前,实现一个简单功能往往需要写一个匿名类,例如:
interface Greeting {
void sayHello();
}
public class Main {
public static void main(String[] args) {
Greeting greeting = new Greeting() {
@Override
public void sayHello() {
System.out.println("传统写法:Hello!");
}
};
greeting.sayHello();
}
}
使用Lambda表达式写法,
interface Greeting {
void sayHello();
}
public class Main {
public static void main(String[] args) {
// 使用Lambda表达式创建 实现函数式接口
Greeting greeting = () -> System.out.println("Lambda表达式:Hello!");
greeting.sayHello();
}
}
Lambda表达式更简洁,直接表达函数实现。
Lambda表达式的几种形式:
- 无参数,单行语句,
() -> System.out.println("Hello"),方法体只有一行代码时,可省略大括号。 - 单参数,单行语句,
x -> System.out.println(x);,只有一个参数时,可省略括号, - 多参数,多行语句,
(a, b) -> { return a + b; },方法体多行代码时,需要大括号 - 省略return,
(a, b) -> a + b,只有一行返回语句时,可省略return。
示例
计算机效果
例如使用Lambda表达式实现计算机的功能,
// 计算机接口
@FunctionalInterface
interface Calculator {
// 只有一个方法
int calculate(int a, int b);
}
public class Main {
public static void main(String[] args) {
// 使用Lambda表达式实现函数接口
Calculator addition = (a, b) -> a + b;
Calculator multiplication = (a, b) -> a * b;
// 加法和乘法效果
System.out.println("加法效果:" + addition.calculate(5, 3));
System.out.println("乘法效果:" + multiplication.calculate(5, 3));
}
}
输出:
14:52:14
加法效果:8
14:52:14
乘法效果:15
实现线程任务
使用Runnable接口实现线程任务:
传统重写Runnable接口方法,
package java.lang;
/**
* Represents an operation that does not return a result.
*
* <p> This is a {@linkplain java.util.function functional interface}
* whose functional method is {@link #run()}.
*
* @author Arthur van Hoff
* @see java.util.concurrent.Callable
* @since 1.0
*/
@FunctionalInterface
public interface Runnable {
/**
* Runs this operation.
*/
void run();
}
重写
public class TestLambda {
public static void main(String[] args) {
// 传统重写Runnable接口run方法
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("传统写法:线程执行中...");
}
});
}
}
可以看见,Runnable是Java中最经典、最基础的函数式接口之一。
判断一个接口是不是函数式接口的唯一标准是:它有且仅有一个抽象方法。
Runnable 接口中只有一个抽象方法:void run();
因此,它完美契合了 Lambda 表达式的替换规则。这也是为什么你可以用 () -> { … } 这种极其简洁的语法来替代以前冗长的匿名内部类去创建线程。这也正是 Java 8 能够用 Lambda 优雅地开启多线程的根本原因。
new Thread(() -> {
System.out.println("Lambda写法:线程执行中...");
}).start();
又或者:
new Thread(() -> {
// thread1 的业务逻辑...
}, "thread1").start();
这里的 () -> { … } 就是在定义这个子线程要干什么活;而后面的 “thread1” 则是给这个线程起了一个名字,方便在控制台打印日志时区分。Thread(() -> {}) 只是把以前又长又丑的“匿名内部类”换成了现代 Java 推荐的、更优雅的 Lambda 语法糖,本质上它们做的事情是一模一样的。
集合遍历与操作
传统方式下,需要写for-each循环或获取迭代器来遍历集合,有了Lambda,配合Stream API,代码变得及其优雅:
List<String> list = Arrays.asList("Alice", "Bob", "Charlie");
// 传统写法
for (String name : list) {
System.out.println(name);
}
// Lambda写法
list.forEach(name -> System.out.println(name));
// 进阶简写
list.forEach(System.out::println);
事件监听器处理
在 Swing/JavaFX 等图形界面开发中,以前为按钮绑定点击事件需要写一大段匿名内部类,现在只需一行:
JButton button = new JButton("点击我");
// Lambda直接传递点击后的行为逻辑,意图一目了然
button.addActionListener(e -> System.out.println("按钮被触发了!"));
自定义排序接口
对集合进行复杂排序时,Lambda 能让比较逻辑非常清晰:
List<String> words = Arrays.asList("Java", "Python", "C++");
// 按字符串长度进行升序排序
words.sort((a, b) -> a.length() - b.length());
异步计算与回调
在处理耗时的异步任务时,Lambda让链式调用变得极度流畅:
CompletableFuture.supplyAsync(() -> fetchData()) // 异步去拉取数据
.thenAccept(result -> process(result)); // 拿到结果后自动处理
方法引用
双冒号::
这是 Lambda 的进一步“终极简写”。如果 Lambda 的方法体仅仅是调用了一个现成的方法,就可以直接用 类名::方法名 替代。
例如:(s) -> System.out.println(s) 可以直接写成 System.out::println。
更多推荐

所有评论(0)