版权声明:本文为博主原创文章,转载请注明出处:http://blog.csdn.net/liudongdong0909。 https://blog.csdn.net/liudongdong0909/article/details/77345079
相关源码地址:https://github.com/liudongdong0909/java8/tree/master/java8-Lambda/src/com/donggua
一、什么是函数式接口
- 只包含一个抽象方法的接口, 称为函数式接口。
- 可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常, 那么该异常需要在目标接口的抽象方法上进行声明)
- 可以再任意函数式接口上使用 @FunctionalInterface 注解, 这样可以检查他是否是一个函数式接口, 同时 javadoc 也会包含一条声明, 说明这个接口是一个函数式接口。
二、自定义函数式接口
函数式接口中使用泛型
三、作为参数传递Lambda表达式
为了将 Lambda 表达式作为参数传递, 接收 lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口的类型
四、java8内置四大核心函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer< T> 消费型接口 |
T | void | 对类型为T的对象应用操作,包含方法: void accept(T t) |
Supplier< T> 供给型接口 |
无 | T | 返回类型为T的对象,包含方法: T get(); |
Function< T,R> 函数型接口 |
T | R | 对类型为T的对象应用操作,并返回结果是R类型的对象。包含方法: R apply(T t); |
Predicate< T> 断定型接口 |
T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean值,包含方法 boolean test (T t) |
五、其他接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
BiFunction< T, U, R> | T, U | R | 对类型为 T,U 参数应用 操作,返回 R 类型的结 果。包含方法为 R apply(T t, U u); |
UnaryOperator< T> (Function子接口) |
T | T | 对类型为T的对象进行一 元运算,并返回T类型的 结果。含方法为 T apply(T t); |
BinaryOperator< T> (BiFunction 子接口) |
T, T | T | 对类型为T的对象进行二 元运算,并返回T类型的结果。包含方法为 T apply(T t1, T t2); |
BiConsumer< T, U> | T, U | void | 对类型为T, U 参数应用 操作。包含方法为 void accept(T t, U u) |
ToIntFunction< T> ToLongFunction< T> ToDoubleFunction< T> |
T | int long double | 分别计算int、long、 double、值的函数 |
IntFunction< R> LongFunction< R> DoubleFunction< R> |
int long double | R | 参数分别为int、long、 double 类型的函数 |
六、综合案例
6.1 创建一个员工集合
// 来一个综合案例看看
List<Employee> emps = Arrays.asList(
new Employee(101, "林青霞", 28, 9889.99),
new Employee(102, "东方不败", 29, 4329.85),
new Employee(103, "周星驰", 40, 1233.88),
new Employee(104, "大圣", 500, 5000.44),
new Employee(105, "张无忌", 15, 3000.09)
);
6.2 两个需求
- 获取所有年龄小于30 的 Employee
- 获取工资大于 4000 的 Employee
6.3 第一种处理方式:使用foreach处理
// 获取所有年龄小于30 的 Employee
public List<Employee> filterEmployeeAge(List<Employee> list) {
List<Employee> employees = new ArrayList<>();
for (Employee employee : list) {
if (employee.getAge() <= 30) {
employees.add(employee);
}
}
return employees;
}
@Test
public void test4() {
List<Employee> employees = this.filterEmployeeAge(emps);
for (Employee employee : employees) {
System.out.println(employee);
}
}
// 获取工资大于 4000 的 Employee
public List<Employee> filterEmployeeSalary(List<Employee> list) {
List<Employee> employees = new ArrayList<>();
for (Employee employee : list) {
if (employee.getSalary() >= 4000) {
employees.add(employee);
}
}
return employees;
}
@Test
public void test5() {
List<Employee> employees = this.filterEmployeeSalary(emps);
for (Employee employee : employees) {
System.out.println(employee);
}
}
缺点:代码冗余严重, 没有使用设计模式优化,如果再加几个根据姓名等条件过滤,就更加明显
6.4 优化方式一:使用策略模式 进行重构
创建一个自定义接口 MyPredicate< Employee>
创建根据年龄过滤的类并实现自定义接口
创建根据薪资过滤的类并实现自定义接口
定义获取过滤之后数据的方法
完成需求:
- 执行结果
6.5 优化方式二:使用函数式接口
将优化方式一中的 MyPredicate< T> 重新定义为函数式接口,使用注解 @FunctionalInterface:
代码调用:
6.6 优化方式三:Lambda表达式
6.7 优化方式四:Stream API
执行结果:
相关源码地址:https://github.com/liudongdong0909/java8/tree/master/java8-Lambda/src/com/donggua