一、什么是函数式编程
函数式编程是一种编程范式,它将计算过程视为数学函数的求值,并且避免使用可变状态和副作用。
简单说,它有两个最基本的特点:
- 函数是"第一等公民"
- 只用"表达式",不用"语句"
所谓"第一等公民"(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
二、Lambda表达式是什么
Lambda表达式是一种匿名函数,它没有函数名,但有参数列表、函数体、返回类型。
在Java中,Lambda表达式的基本语法是:
(参数) -> { 函数体 }
最简单的例子:
Function<Integer, Integer> square = x -> x * x;
上面代码中,x -> x * x就是一个Lambda表达式,它接受一个参数x,返回x的平方。
三、函数式编程的三大特点
1. 无副作用
传统的编程方式经常会改变程序的状态,比如修改全局变量。这种"副作用"会使代码变得难以理解和调试。
看下面的例子:
// 有副作用的写法
int sum = 0;
for (int i = 1; i <= 5; i++) {
sum += i;
}
System.out.println("Sum: " + sum);
// 无副作用的函数式写法
int result = Stream.of(1, 2, 3, 4, 5)
.reduce(0, Integer::sum);
System.out.println("Sum: " + result);
第一种写法,循环过程中不断改变 sum
变量的值,这就是副作用。
第二种写法,数据的处理过程没有改变任何外部变量,这就避免了副作用。
2. 纯函数
所谓纯函数,是指同样的输入,永远得到同样的输出,而且没有任何可观察的副作用。
举个例子:
// 纯函数示例
public static int square(int n) {
return n * n;
}
不管调用多少次 square(5)
,返回值都是 25
,而且不会改变任何外部状态。
3. 高阶函数
高阶函数是指可以接受函数作为参数,或者返回一个函数的函数。
// 接受函数作为参数
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> doubled = numbers.stream()
.map(n -> n * 2)
.collect(Collectors.toList());
// 返回函数的函数
public static Function<Integer, Integer> multiplier(int factor) {
return n -> n * factor;
}
Function<Integer, Integer> doubler = multiplier(2);
System.out.println(doubler.apply(5)); // 输出10
四、实际应用示例
函数式编程最常用的三种操作是Map(映射)、Filter(过滤)和Reduce(归约)。下面通过具体例子来说明。
1. Map(映射)
Map操作就是将一个函数应用到集合的每个元素上,然后得到一个新的集合。
List<String> names = Arrays.asList("张三", "李四", "王五");
// 传统写法
List<Integer> lengths = new ArrayList<>();
for (String name : names) {
lengths.add(name.length());
}
// 函数式写法
List<Integer> lengths = names.stream()
.map(String::length)
.collect(Collectors.toList());
2. Filter(过滤)
Filter操作就是按照条件过滤集合中的元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
// 传统写法
List<Integer> evens = new ArrayList<>();
for (Integer n : numbers) {
if (n % 2 == 0) {
evens.add(n);
}
}
// 函数式写法
List<Integer> evens = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
3. Reduce(归约)
Reduce操作是把集合中的所有元素按照某种规则组合起来。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 传统写法
int sum = 0;
for (Integer n : numbers) {
sum += n;
}
// 函数式写法
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
评论区