1. 函数式编程
百度对函数式编程是这样定义的:
函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。
和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。
和过程化编程相比,函数式编程里函数的计算可随时调用。
这个定义非常学术化,我是这样理解的:函数式编程就是函数以lambda表达式的形式,作为参数,传递另一个函数。
2. 函数式编程接口
被@FunctionalInterface标记的接口就是函数式编程接口,它有且只有一个抽象方法,lambda表达式是函数式编程的具体表现形式。函数式编程接口能够被自动推导。
3. Java8函数式编程接口
Java8里提供了四个顶层的函数式编程接口,分别是:
1. Suplier,表示提供一个值,也就是lambda表达式需要返回一个值。
2. Consumer, 表示消耗一个值,也就是lambda表达式需要一个参数。
3.Function<T,R>, 表示消耗一个值,把这个值从T转换成R, 也就是lambda表达式需要一个参数,同时返回一个结果。
4.Predicate, 表示测试一个值,判断它的真伪,也就是lambda表达式接受一个参数,返回一个boolean值。
其它的就是这四个顶层接口的变体了,我总结了一下,如下图:
4. 函数式编程接口应用
我们用常见的分页查询功能举个例子。
假设一个项目,有很多张表,其中有一部分需要分页查询,拿用户表举个例子,代码可能是这样的
public PageInfo<User> queryUserList(int pageNum, int pageSize) {
try {
if(pageNum < 0) {
pageNum = 1;
}
if(pageSize < 0) {
pageSize = 10;
}
PageHelper.startPage(pageNum, pageSize);
List<User> userList = userMapper.selectAll();
PageInfo<User> pageInfo = new PageInfo<User>(userList);
return pageInfo;
} catch (Exception e) {
return null;
}
}
不同的表,大概率只有sql语句不同,其它的地方都一样。如果复制黏贴,会有比较多的代码冗余,怎么改进呢?
考虑使用lambda表达式的形式,sql语句是在做什么呢?本质上它提供一个值,所以我们可以用Supplier,配合上泛型,我们可以把分页的代码改进成如下的形式:
protected <T> PageInfo<T> getPageInfo(int pageNum, int pageSize, Supplier<List<T>> supplier) {
try {
if(pageNum < 0) {
pageNum = 1;
}
if(pageSize < 0) {
pageSize = 10;
}
PageHelper.startPage(pageNum, pageSize);
List<T> list = supplier.get();
PageInfo<T> info = new PageInfo(list);
return info;
} catch (Exception e) {
log.error("getPageInfo error " + e.getMessage(), e);
return null;
}
}
调用的方式如下,这样我们只要提供不同的sql语句就可以了。
public PageInfo<User> queryUserList(int pageNum, int pageSize) {
return getPageInfo(pageNum, pageSize, ()->{
return userMapper.selectAll();
});
}