Java函数式编程
发表于 2025/04/23
0
Java Lambda 表达式与函数式编程
Lambda 表达式是 Java 8 引入的一个重要特性,它使得 Java 能够支持更简洁的函数式编程风格。Lambda 表达式的引入主要是为了简化代码,尤其是在处理集合、事件监听器和回调函数时,让代码更加简洁和易于理解。
1. Lambda 表达式的基本语法
Lambda 表达式的一般语法形式如下:
(parameters) -> expression
- parameters:表示输入参数,可以有一个或多个。
- ->:Lambda 操作符,用于将参数与表达式分开。
- expression:表示 Lambda 表达式的主体部分,可以是一个简单的表达式或一个代码块。
2. Lambda 表达式的示例
- 无参数的 Lambda 表达式
Runnable r = () -> System.out.println("Hello, Lambda!");
r.run(); // 输出: Hello, Lambda!
单一参数的 Lambda 表达式
// 使用一个参数并返回该参数的平方
Function<Integer, Integer> square = x -> x * x;
System.out.println(square.apply(5)); // 输出: 25
多个参数的 Lambda 表达式
// 使用两个参数并返回它们的和
BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
System.out.println(sum.apply(3, 4)); // 输出: 7
- 带有代码块的 Lambda 表达式
// 计算两个数的和,并打印
BiFunction<Integer, Integer, Integer> sumAndPrint = (a, b) -> {
System.out.println("Adding " + a + " and " + b);
return a + b;
};
System.out.println(sumAndPrint.apply(3, 4)); // 输出: Adding 3 and 4
// 输出: 7
3. 函数式接口
Lambda 表达式通常与函数式接口一起使用。函数式接口是一个只包含一个抽象方法的接口。
- 示例 1:
Runnable
接口
Runnable r = () -> System.out.println("Hello, World!");
new Thread(r).start();
- 示例 2: 自定义函数式接口
@FunctionalInterface
interface MyFunction {
int apply(int x, int y);
}
public class LambdaExample {
public static void main(String[] args) {
MyFunction sum = (a, b) -> a + b;
System.out.println(sum.apply(10, 20)); // 输出: 30
}
}
4. 常用函数式接口
Java 8 提供了一些常用的函数式接口,这些接口已经定义在 java.util.function
包中:
Predicate<T>
:表示一个接受 T 类型参数并返回 boolean 的函数。Function<T, R>
:表示一个接受 T 类型参数并返回 R 类型结果的函数。Consumer<T>
:表示一个接受 T 类型参数并没有返回值的函数。Supplier<T>
:表示一个没有输入参数并返回 T 类型结果的函数。BiFunction<T, U, R>
:表示一个接受 T 和 U 类型参数并返回 R 类型结果的函数。
5. Lambda 表达式的应用案例
集合遍历与过滤
使用 Lambda 表达式简化集合遍历和过滤操作:
List<String> names = Arrays.asList("John", "Jane", "Jack", "Mike", "Tom");
names.stream()
.filter(name -> name.startsWith("J"))
.forEach(System.out::println); // 输出: John, Jane, Jack
排序操作
Lambda 表达式可以简化排序操作:
List<String> names = Arrays.asList("John", "Jane", "Jack", "Mike", "Tom");
names.sort((s1, s2) -> s1.compareTo(s2)); // 升序排序
names.forEach(System.out::println);
映射与转换
使用 map()
函数来进行集合元素的转换:
List<String> names = Arrays.asList("John", "Jane", "Jack");
List<String> upperCaseNames = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(upperCaseNames); // 输出: [JOHN, JANE, JACK]
收集与分组
使用 Collectors
类来收集数据并进行分组:
List<Person> people = Arrays.asList(
new Person("John", 25),
new Person("Jane", 30),
new Person("Tom", 25)
);
Map<Integer, List<Person>> groupedByAge = people.stream()
.collect(Collectors.groupingBy(Person::getAge));
groupedByAge.forEach((age, p) -> {
System.out.println("Age: " + age);
p.forEach(person -> System.out.println(person.getName()));
});
6. 函数式编程的特点与优势
- 简洁性:Lambda 表达式让代码变得更简洁,减少了冗余代码。
- 可读性:通过移除匿名内部类,提高了代码的可读性。
- 惰性计算:Lambda 表达式结合
Stream
API 允许惰性计算,可以优化性能。 - 并行处理:通过
Stream
API,可以轻松地将代码转换为并行计算模式。
7. 函数式编程的高级应用
- 高阶函数:可以将函数作为参数传递或返回。
// 高阶函数:将函数作为参数
public static void printFiltered(List<String> list, Predicate<String> condition) {
list.stream().filter(condition).forEach(System.out::println);
}
printFiltered(names, name -> name.startsWith("J"));
- 组合函数:可以使用
andThen()
或compose()
方法将多个函数组合在一起。
Function<Integer, Integer> multiplyBy2 = x -> x * 2;
Function<Integer, Integer> add3 = x -> x + 3;
Function<Integer, Integer> combined = multiplyBy2.andThen(add3);
System.out.println(combined.apply(5)); // 输出: 13 (5*2 + 3)
- 不可变性:函数式编程强调使用不可变对象,避免副作用。
// 使用 Java 8 Immutable Collections
List<String> immutableList = List.of("a", "b", "c");
总结
Java 中的 Lambda 表达式和函数式编程给我们提供了更简洁、更易读的代码写法。通过结合 Stream
API,Lambda 使得集合处理变得更加灵活,能够在实现并行计算、函数式变换和高阶函数等方面发挥巨大作用。