JDK8系列之使用Function函数式接口

一、函数式接口是jdk8的新特性之一,函数式接口是只包含一个抽象方法声明的接口。按分类主要分为四大接口类型: Function、Consumer、Predicate、Supplier。

接口参数返回值说明
Supplier<T>T供给型,无参,返回一个指定泛型的对象
Consumer<T>T消费型,传入一个指定泛型的参数,无返回值
Predicate<T>TBoolean断言型,判断函数,返回true或者false
Function<T,R>TR方法型,输入一个参数,返回一个结果

也可以直接去java.util.function包里面看,jdk提供了很多函数式接口。比如

序号函数式接口描述说明
1BiConsumer<T,U>代表了一个接受两个输入参数的操作,并且不返回任何结果
2BiFunction<T,U,R>代表了一个接受两个输入参数的方法,并且返回一个结果

二、实战一:用函数式接口实现回调

员工执行业务逻辑完成任务后,老板收到回调通知。

1.Employee员工类

/**
 * 员工类
 *
 * @author zsh
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee<T, C> {
    /**
     * 员工的名字
     */
    private String name;
    /**
     * 员工处理任务的逻辑
     */
    private Function<T, C> taskFunction;

    /**
     * 处理任务的方法
     *
     * @param boss 发布任务的老板对象,包含老板名称,任务及回调
     */
    protected void doTask(Boss<T, C> boss) {
        if (null == boss || null == boss.getTask()) {
            throw new IllegalArgumentException("boss is not ready...");
        }
        if (null == this.taskFunction) {
            throw new IllegalArgumentException("employee has no skills for task...");
        }
        //执行任务的实际方法
        C callback = taskFunction.apply(boss.getTask());
        //将结果发送给老板
        boss.callback(this, callback);
    }
}

2.Boss老板类

/**
 * 老板类
 *
 * @author zsh
 */

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Boss<T, C> {
    /**
     * 老板的名字
     */
    private String name;
    /**
     * 老板待发布的任务
     */
    private T task;
    /**
     * 老板处理回调的方法
     */
    private BiConsumer<Employee<T, C>, C> callbackConsumer;

    /**
     * 指定员工去完成老板的任务
     * 员工完成任务后回调老板的接口
     *
     * @param employee 指定的员工
     */
    public void assignTask(Employee<T, C> employee) {
        employee.doTask(this);
    }

    /**
     * 完成任务后的回调
     *
     * @param employee
     * @param callback
     */
    protected void callback(Employee<T, C> employee, C callback) {
        if (null != callback && null != callbackConsumer) {
            callbackConsumer.accept(employee, callback);
        }
    }
}

3.CallBackService回调service

/**
 * 回调service
 *
 * @author zsh
 */
@Service
public class CallBackService {
    /**
     * 回调方法
     */
    public <T, C> void bossAssignTask() {
        //初始化老板对象,指定名称,任务和处理回调的逻辑
        Boss<T, C> bossA = new Boss<>(
                "bossA",
                (T) "a任务",
                (e, c) -> System.out.println("BossA收到" + e.getName() + "的回调啦..." + c.toString())
        );
        //初始化员工对象,指定名称和处理任务的逻辑
        Employee<T, C> employee = new Employee<>(
                "employee",
                t -> {
                    System.out.println("【员工A】收到任务" + t.toString() + "啦...");
                    try {
                        //通过睡眠,模拟执行任务
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("【员工A】完成任务" + t.toString() + "啦...");
                    return (C) "确认了处理结果";
                });
        //老板给员工安排任务,员工完成任务后老板会收到回调
        bossA.assignTask(employee);
        //员工可以换一个处理这个任务的逻辑
        employee.setTaskFunction(t -> {
            System.out.println("【员工A新逻辑】收到任务" + t.toString() + "啦...");
            try {
                //通过睡眠,模拟执行任务
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("【员工A新逻辑】完成任务" + t.toString() + "啦...");
            return (C) "确认了新逻辑处理结果";
        });
        //老板继续给员工安排任务
        bossA.assignTask(employee);
        //老板有了新任务
        bossA.setTask((T) "b任务");
        //老板继续给员工安排任务
        bossA.assignTask(employee);
        //老板有新的回调逻辑
        bossA.setCallbackConsumer((e, c) -> System.out.println("BossA新的回调方法收到" + e.getName() + "的回调啦..." + c.toString()));
        //老板继续给员工安排任务
        //bossA.assignTask(employee);
    }
}

4.CallBackController回调controller

/**
 * 回调Controller
 *
 * @author zsh
 */
@RestController
@RequestMapping("/callBackController")
public class CallBackController {
    @Autowired
    private CallBackService callBackService;

    @RequestMapping("/callBackBossAssignTask")
    public boolean callBackBossAssignTask() {
        callBackService.bossAssignTask();
        return true;
    }

}

5.测试结果

在这里插入图片描述
在这里插入图片描述

6.代码结构及下载地址

在这里插入图片描述

三、利用Function函数优化if else逻辑

1.由于Function接口的入参只支持一个参数,所以自定义一个MyFunction,支持多个参数

@FunctionalInterface
public interface MyFunction<T, R> {
    R apply(T... t);
}

2.业务服务FunctionService

@Service
public class FunctionService {
    public static Map<String, MyFunction<Object, String>> map = new HashMap<>();

    @PostConstruct
    public void init() {
        map.put("A", FunctionService::fun01);
        map.put("B", FunctionService::fun02);
        map.put("C", FunctionService::fun03);
    }

    private static String fun03(Object... o) {
        System.out.println("fun03=====>");
        for (Object o1 : o) {
            System.out.println(o1);
        }
        return "CCC";
    }

    private static String fun02(Object... o) {
        System.out.println("fun02=====>");
        for (Object o1 : o) {
            System.out.println(o1);
        }
        return "BBB";
    }

    private static String fun01(Object... o) {
        System.out.println("fun01=====>");
        for (Object o1 : o) {
            System.out.println(o1);
        }
        return "AAA";
    }

    public String getFunctionResult(String type, String value, Integer num) {
        // 以前的if-else
        /*
        if(type.equals("A")){
            fun01("a", 1);
        }else if(type.equals("B")){
            fun02("b", 2);
        }else if(type.equals("C")){
            fun03("c", 3);
        }
        */
        // 优化的if-else
        return map.get(type).apply(value, num);
    }
}

3.控制层

@RequestMapping("/functionController")
@RestController
public class FunctionController {
    @Autowired
    private FunctionService functionService;

    @RequestMapping("/doFunctionByType")
    public String doFunctionByType(String type, String value, Integer num) {
        return functionService.getFunctionResult(type, value, num);
    }
}

4.执行结果测试

结果1
在这里插入图片描述
在这里插入图片描述
结果2
在这里插入图片描述
在这里插入图片描述

5.代码结构

在这里插入图片描述

6.通过map + 函数式的方式处理if-else业务逻辑

 /**
     * 传统根据不同条件判断执行不同业务逻辑
     *
     * @param num
     * @return
     */
    public String getUserNameByNum(Integer num) {
        User user = new User();
        user.setUserName("张三丰");
        user.setRealName("三丰丰");
        String userName = "";
        switch (num) {
            case 1:
                userName = String.format("我的名字,name:%s", user.getUserName());
                break;
            case 2:
                userName = String.format("我的名字,name:,realName:%s", user.getUserName(), user.getRealName());
                break;
            default:
                break;
        }
        return userName;
    }

    //定义一个map跟Function组合使用的map
    private final ImmutableMap<Integer, Function<User, String>> PERSON_TYPE_MAP = ImmutableMap.<Integer, Function<User, String>>builder()
            .put(1, person -> String.format("武当山No1,userName:%s", person.getUserName()))
            .put(2, person -> String.format("武当山No1,userName:%s,realName:%s", person.getUserName(), person.getRealName()))
            .build();

    //调用
    public String getFunctionUserNameByNum(Integer num) {
        User user = new User();
        user.setUserName("张三丰");
        user.setRealName("三丰丰");
        return PERSON_TYPE_MAP.get(num).apply(user);
    }
//通过Function获取用户名
    @RequestMapping("/getFunctionUserNameByNum")
    public String getFunctionUserNameByNum(int num) {
        return userService.getFunctionUserNameByNum(num);
    }

在这里插入图片描述
在这里插入图片描述

四、 项目源码下载 spring-boot2.-xlearn 欢迎Star

参考资料
JDK8系列之使用Function函数式接口实现回调
java8 函数式接口 实现回调
ImmutableMap使用分析
map与函数式编程篇

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值