JAVA8新特性[第二季]-函数式接口

版权声明:本文为博主原创文章,转载请注明出处: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

一、什么是函数式接口

  1. 只包含一个抽象方法的接口, 称为函数式接口。
  2. 可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常, 那么该异常需要在目标接口的抽象方法上进行声明)
  3. 可以再任意函数式接口上使用 @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 两个需求

  1. 获取所有年龄小于30 的 Employee
  2. 获取工资大于 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 优化方式一:使用策略模式 进行重构

  1. 创建一个自定义接口 MyPredicate< Employee>
    这里写图片描述

  2. 创建根据年龄过滤的类并实现自定义接口
    这里写图片描述

  3. 创建根据薪资过滤的类并实现自定义接口
    这里写图片描述

  4. 定义获取过滤之后数据的方法
    这里写图片描述

  5. 完成需求:
    这里写图片描述

  6. 执行结果
    这里写图片描述

6.5 优化方式二:使用函数式接口

将优化方式一中的 MyPredicate< T> 重新定义为函数式接口,使用注解 @FunctionalInterface:
这里写图片描述

代码调用:
这里写图片描述

6.6 优化方式三:Lambda表达式

这里写图片描述

6.7 优化方式四:Stream API

这里写图片描述

执行结果:
这里写图片描述

相关源码地址:https://github.com/liudongdong0909/java8/tree/master/java8-Lambda/src/com/donggua

猜你喜欢

转载自blog.csdn.net/liudongdong0909/article/details/77345079