函数式编程(Functional Programming,FP)是一种编程范式,它将计算过程视为数学函数的求值,并避免使用程序状态和可变数据。函数式编程的核心思想是使用纯函数(Pure Functions)和不可变数据(Immutable Data)来构建程序。函数式编程可以减少代码量,提高生产力
例如: 有如下类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class User {
private final Integer id;
private final String name;
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public static List<User> filter(List<User> users, Predicate<User> predicate) {
List<User> results = new ArrayList<>();
for (User user : users) {
if (predicate.test(user)) {
results.add(user);
}
}
return results;
}
}
|
本质是从一种关系到另一种关系的映射
通过Lambda
表达式过滤姓王的用户
1
2
3
4
5
|
// 过滤姓王的用户
public static List<User> filterWangUser(List<User> users) {
return filter(users, user -> user.getName().startsWith("王"));
// user -> user.getName().startsWith("王") // 就是lambda表达式
}
|
本质也是从一种关系到另一种关系的映射
通过方法引用
过滤姓王的用户
1
2
3
4
5
6
7
8
9
|
public static boolean isWang(User user) {
return user.getName().startsWith("王");
}
// 过滤姓王的用户
public static List<User> filterWangUser(List<User> users) {
return filter(users, User::isWang);
// User::isWang // 就是方法引用
}
|
你可能会疑惑,为什么方法引用
和Lambda
表达式可以被放到filter
方法中的Predicate
上?
我们说过了,Lambda
表达式和方法引用
实际上都是一种关系到另一种关系的映射
我们来看看Predicate
接口的定义
1
2
3
4
5
6
7
8
9
10
11
12
|
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
}
|
Predicate
接口定义了一个对象(T)
到boolean
的转换关系,你给我一个对象
我把它变成一个boolean
值给你,因此所有满足了这个映射关系
的方法都可以被传递给Predicate
接口,这种接口我们称为函数接口
再来看上面的Lambda
表达式和方法引用
1
2
3
4
5
|
user -> user.getName().startsWith("王")
// 我们把它拆分为两部分
user // 输入 user 它是一个User类型
-> user.getName().startsWith("王") // 输出,它是一个boolean类型
// 因此这个Lambda表达式满足Predicate接口,因此它可以被传递给Predicate
|
1
2
3
4
|
public static boolean isWang(User user) {
return user.getName().startsWith("王");
}
// 这个就更好理解了,输入是User,输出是boolean,因此它也满足Prodicate接口
|
方法引用
相比Lambda
表达式的好处是它有名字,更易于理解它在做什么
任何只包含一个抽象方法的接口都可以被自动的转换为函数接口
- java.util.function.*
- Consumer
- Predicate
- Function
- Supplier
按照什么排序,它应用了Function
接口,输入一个类型,按照输出的结果排序