玩转Java8新特性

背景

说到Java8新特性,大家可能都耳濡目染了,代码中经常使用遍历stream流用到不同的api了,但是大家有没有想过自己也自定义个函数式接口呢,目前Java8自带的四个函数式接口,比如Function、Supplier等
stream流中也使用到了,但是这四个函数式接口不仅仅只是为了遍历stream流而产生的,可以在别的地方也可以单独使用这个四个函数式接口,甚至四个不够可以自定义一个都可以

自定义函数式接口

@FunctionalInterface
public interface StatusProcessFunction {

    /**
     * 整车大版本策略-有效/无效处理逻辑
     *
     * @param status 有效:1 无效:0
     * @return void
     **/
    void statusMessageProcess(String status);
}
    /**
     * 如果参数为有效:1 ---> 该目标大版本下所有原版本策略都是有效的,可以继续
     * 反之无效:0 ----> 该目标大版本下所有原版本策略都是无效的,需要将策略都设置失效状态 2、策略关联的任务都设置为失效状态
     *
     * @param status 有效:1 无效:0
     * @return com.adups.iov.open.api.vsp.service.StatusProcessFunction
     **/
    private StatusProcessFunction isValid(String status, String versionCode) {
        return (errorMessage) -> {
            if (Objects.equals(status, ZERO)) {
                // 通过目标大版本号且是有效状态的获取所有的关联任务id
                List<TaskStrategyInfoDO> taskStrategyInfoDOS = bigVersionInfoMapper.queryTaskIdsByVersionCode(versionCode);
                boolean anyMatchTask = taskStrategyInfoDOS.stream().anyMatch(s -> !ObjectUtils.isEmpty(s.getTaskId()));
                if (anyMatchTask) {
                    // 批量修改任务的状态置为已失效
                    strategyInfoMapper.updateTaskStatusByVersionCode(taskStrategyInfoDOS);
                }
                boolean anyMatchStrategy = taskStrategyInfoDOS.stream().anyMatch(s -> !ObjectUtils.isEmpty(s.getStrategyId()));
                if (anyMatchStrategy) {
                    // 批量修改策略的状态置为已失效
                    strategyInfoMapper.updateStrategyStatusByVersionCode(taskStrategyInfoDOS);
                }
                log.info("整车大版本策略-目标大版本已置为失效状态,目标版本下的策略和任务均置为已失效:status -->{}," +
                        "versionCode-->{},业务异常信息:{}", status, versionCode, errorMessage);
            }
        };
    }
    /**
     * 保存整车大版本策略信息
     *
     * @param {@link versionStrategyInfoDTO}<{@link VehicleVersionStrategyInfoDTO}> 整车大版本策略信息入参模型
     * @return BigVersionInfoDO 返回整车大版本策略信息(包含主键id)
     */
    private BigVersionInfoDO saveBigVersionInfo(VehicleVersionStrategyInfoDTO versionStrategyInfoDTO) {
        // 构建BigVersionInfoDO对象-填充入库属性
        BigVersionInfoDO bigVersionConvertDO = StrategyInfoConvert.INSTANCE.dtoStrategyBigVersionConvertDO(versionStrategyInfoDTO.getVehicleBigVersion());
        bigVersionConvertDO.setModelId(vehicleModelMapper.getModelIdByElectricalPlatform(bigVersionConvertDO.getElectricalPlatform()));
        // 新增整车大版本信息如果重复就更新否则就插入
        isValid(bigVersionConvertDO.getStatus(), bigVersionConvertDO.getVersionCode()).statusMessageProcess(DataSyncConstant.PO_STRATEGY_RESPONSE_LOG);
        bigVersionInfoMapper.saveBigVersionInfo(bigVersionConvertDO);
        return bigVersionConvertDO;
    }

函数式接口替代策略模式(Supplier)

说到策略模式,大家肯定都用到过我之前有篇已经说过策略模式+工厂方法
大家其实都知道有时候设计模式并不是为了简化代码的,更多的是为了扩展性的,但是有时候并不是适用所有场景,当然通过不同类型发生不同的行为,前提这些行为的步骤都是一样的,只是有些行为的内容不一样,这个时候你当然可以使用策略模式+工厂方法,但是也可以使用函数式接口

需求

现在有四个控制层,但是业务层都可以封装一个,只是参数不同而已,当然你也可以都拆开,但是这些肯定idea会提示很多重复代码嘛,对于这种就可以传入一个函数式接口作为形参

在这里插入图片描述

@Slf4j
@RestController
public class PackageInfoSyncController {

    @Autowired
    private VspAsyncServiceCommonHandle serviceCommonHandle;

    /**
     * 软件包信息同步
     *
     * @param requestDTO po入参
     * @return POResponseVO
     */
    @PostMapping("/ota/package/info")
    public POResponseVO packageInfoParse(@RequestBody PORequestDTO requestDTO) {
        return serviceCommonHandle.asyncServiceCommonHandle(requestDTO, () -> MapUtil.builder()
                .put(DataSyncConstant.TYPE, DataSyncEnum.PACKAGE_INFO.getType())
                .put(DataSyncConstant.RESPONSE, DataSyncConstant.PO_PACKAGE_RESPONSE_EXISTED_LOG)
                .put(DataSyncConstant.RESULT, DataSyncConstant.PO_PACKAGE_RESPONSE_LOG)
                .build());
    }
}
    /**
     * VSP平台策略信息同步信息
     *
     * @param requestDTO  同步数据
     * @param mapSupplier mapSupplier
     * @return {@link POResponseVO}
     */
    public POResponseVO asyncServiceCommonHandle(PORequestDTO requestDTO, Supplier<Map<Object, Object>> mapSupplier) {
      ...中间的业务代码都省略
     String hashCount = strategyInfoMapper.querySyncStrategyInfo(hash, (Integer)mapSupplier.get().get(DataSyncConstant.TYPE));
       return new POResponseVO();
    }

函数式接口替代策略模式(Function)

在Java 8中,您可以使用java.util.function.Function接口来传递行为(功能)作为参数。下面是一个简单的示例,演示如何将相同的代码抽取出来,并通过Function函数式接口传递不同的行为:

import java.util.function.Function;

public class FunctionExample {

    public static void main(String[] args) {
        // 示例1:将字符串转换为大写
        String result1 = processString("Hello, World!", str -> str.toUpperCase());
        System.out.println("Result 1: " + result1);

        // 示例2:将字符串转换为小写
        String result2 = processString("Hello, World!", str -> str.toLowerCase());
        System.out.println("Result 2: " + result2);

        // 示例3:将字符串长度加倍
        Integer result3 = processInteger(5, num -> num * 2);
        System.out.println("Result 3: " + result3);
    }

    // 通用方法,接受一个字符串和一个 Function 接口实例
    private static String processString(String input, Function<String, String> function) {
        return function.apply(input);
    }

    // 通用方法,接受一个整数和一个 Function 接口实例
    private static Integer processInteger(Integer input, Function<Integer, Integer> function) {
        return function.apply(input);
    }
}

在上述示例中,processString方法和processInteger方法接受一个泛型参数(字符串或整数),以及一个Function接口的实例作为参数。通过传递不同的Function实例,您可以实现对相同代码的不同行为。在示例中,分别演示了将字符串转换为大写、小写以及将整数加倍的三种不同行为。

函数式接口替代if else(Map+函数式接口)

    public void addNotification(List<VerifyRecordDO> auditRecordAddList) {

        auditRecordAddList.forEach(auditRecordAddDTO -> {

            RBucket<AuditDataVO> bucket = redissonClient.getBucket(BUCKETNAME + (auditRecordAddDTO.getAuditStatus() + 1));
            AuditDataVO auditDataVO = bucket.get();
            if (AuditBusinessTypeEnum.TASK_MODULE.getCode().equals(auditRecordAddDTO.getModuleType())) {
                auditDataVO.setTaskModelSize(auditDataVO.getTaskModelSize()+1);
            }
            if (AuditBusinessTypeEnum.DIAGNOSTIC_DATA_MODULE.getCode().equals(auditRecordAddDTO.getModuleType())) {
                auditDataVO.setDiagnosticDataModelSize(auditDataVO.getDiagnosticDataModelSize()+1);
            }
            if (AuditBusinessTypeEnum.DIAGNOSTIC_FLOW_MODULE.getCode().equals(auditRecordAddDTO.getModuleType())) {
                auditDataVO.setDiagnosticFlowModelSize(auditDataVO.getDiagnosticFlowModelSize()+1);
            }
            if (AuditBusinessTypeEnum.REFRESH_PACKAGE_MODULE.getCode().equals(auditRecordAddDTO.getModuleType())) {
                auditDataVO.setRefreshPackageModelSize(auditDataVO.getRefreshPackageModelSize()+1);
            }

            bucket.set(auditDataVO);

        });
        redissonClient.getTopic(EVERYONE_PERMISSION).publish("");
    }

这个代码块有很多if,而且if里面的逻辑基本上都是大差不差的,只是根据不同的类型给这个对象set不同的属性值,这个时候我们优化下的结果

    public void addNotification(List<VerifyRecordDO> auditRecordAddList) {
        // 适配模式
        Map<Integer, Consumer<AuditDataVO>> modelTypeHandlers = new HashMap<>();
        modelTypeHandlers.put(AuditBusinessTypeEnum.TASK_MODULE.getCode(), vo -> vo.setTaskModelSize(vo.getTaskModelSize()+1));
        modelTypeHandlers.put(AuditBusinessTypeEnum.DIAGNOSTIC_DATA_MODULE.getCode(), vo -> vo.setDiagnosticDataModelSize(vo.getDiagnosticDataModelSize()+1));
        modelTypeHandlers.put(AuditBusinessTypeEnum.DIAGNOSTIC_FLOW_MODULE.getCode(), vo -> vo.setDiagnosticFlowModelSize(vo.getDiagnosticFlowModelSize()+1));
        modelTypeHandlers.put(AuditBusinessTypeEnum.REFRESH_PACKAGE_MODULE.getCode(), vo -> vo.setRefreshPackageModelSize(vo.getRefreshPackageModelSize()+1));

        auditRecordAddList.forEach(auditRecordAddDTO -> {
            RBucket<AuditDataVO> bucket = redissonClient.getBucket(BUCKETNAME + (auditRecordAddDTO.getAuditStatus() + 1));
            AuditDataVO auditDataVO = bucket.get();

            modelTypeHandlers.getOrDefault(auditRecordAddDTO.getModuleType(), vo -> {})
            .accept(auditDataVO);

            bucket.set(auditDataVO);

        });
        //
        redissonClient.getTopic(EVERYONE_PERMISSION).publish("");
    }

自定义函数式接口

定义一个抛出异常的形式的函数式接口, 这个接口只有参数没有返回值是个消费型接口

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值