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

本文介绍了Java8中的函数式接口概念,强调了仅含有一个抽象方法的接口可以被Lambda表达式所表示。文章通过实例展示了如何自定义函数式接口,以及如何将Lambda表达式作为参数传递。讨论了Java8的四大核心函数式接口,并提供了使用策略模式、函数式接口、Lambda表达式以及Stream API优化代码的综合案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相关源码地址: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>
消费型接口
Tvoid对类型为T的对象应用操作,包含方法:
void accept(T t)
Supplier< T>
供给型接口
T返回类型为T的对象,包含方法:
T get();
Function< T,R>
函数型接口
TR对类型为T的对象应用操作,并返回结果是R类型的对象。包含方法:
R apply(T t);
Predicate< T>
断定型接口
Tboolean确定类型为T的对象是否满足某约束,并返回boolean值,包含方法
boolean test (T t)

五、其他接口

函数式接口参数类型返回类型用途
BiFunction< T, U, R>T, UR对类型为 T,U 参数应用 操作,返回 R 类型的结 果。包含方法为
R apply(T t, U u);
UnaryOperator< T>
(Function子接口)
TT对类型为T的对象进行一 元运算,并返回T类型的 结果。含方法为
T apply(T t);
BinaryOperator< T>
(BiFunction 子接口)
T, TT对类型为T的对象进行二 元运算,并返回T类型的结果。包含方法为
T apply(T t1, T t2);
BiConsumer< T, U>T, Uvoid对类型为T, U 参数应用 操作。包含方法为
void accept(T t, U u)
ToIntFunction< T>
ToLongFunction< T>
ToDoubleFunction< T>
Tint long double分别计算int、long、 double、值的函数
IntFunction< R>
LongFunction< R>
DoubleFunction< R>
int long doubleR参数分别为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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值