首页 > 其他分享 >循环处理数据的小轮子

循环处理数据的小轮子

时间:2024-10-08 14:48:47浏览次数:7  
标签:Function startParam 处理 getId dataList 循环 param 轮子 DeptDO

1. 基于某个字段

比如要处理一批数据,把 id 作为查询条件,500 条数据作为一个批次

工具类代码如下:

public class DataLoopUtil {

    /**
     * 基于某个字段(比如 id, createTime 等), 循环处理数据
     * P > Param
     * R > Result
     *
     * @param dataQueryFunction 查询数据
     * @param dataProcessConsumer 处理数据
     * @param extractParamFunction 从 R 中获取 P
     * @param startParam 起始参数
     */
    public static <P, R> void processData(Function<P, List<R>> dataQueryFunction,
                                          Consumer<List<R>> dataProcessConsumer,
                                          Function<R, P> extractParamFunction,
                                          P startParam) {
        List<R> dataList;
        do {
            dataList = dataQueryFunction.apply(startParam);
            if (CollUtil.isNotEmpty(dataList)) {
                log.info("data process result {}", LambdaUtils.mapToList(dataList, extractParamFunction));
                dataProcessConsumer.accept(dataList);
                startParam = extractParamFunction.apply(dataList.get(dataList.size() - 1));
            }
        } while (CollUtil.isNotEmpty(dataList));

        log.info("processData exist start param is {}", startParam);
    }
}

使用代码如下

@Component
public class DataLoopService {

    @Resource
    private MemberUserMapper memberUserMapper;

    public void loopGetMemberInfo() {
        DataLoopUtil.processData(getMemberQueryFn(), getMemberProcessConsumer(), MemberUserDO::getId, 600L);
    }

    // 查数据 Function
    private Function<Long, List<MemberUserDO>> getMemberQueryFn() {
        return startId -> memberUserMapper.selectList(
                new LambdaQueryWrapper<MemberUserDO>().gt(MemberUserDO::getId, startId).last(" limit 3"));
    }

    // 处理数据 Consumer
    private Consumer<List<MemberUserDO>> getMemberProcessConsumer() {
        return dataList -> dataList.forEach(member -> {
            MemberUserDO update = new MemberUserDO();
            update.setId(member.getId());
            update.setRegisterIp(member.getId().toString());
            memberUserMapper.updateById(update);
        });
    }
}

2. 基于上一批字段

比如初始化部门表的 parent_ids,先从第一批开始,然后开始第二批,轮子如下

工具类代码是如下

/**
 * 基于上次结果,循环处理数据
 * 比如查询部门,先用顶级部门 id 查询,查到下级,再用下级的 ids 查下下级
 */
public static <P, R> void processDataBatch(Function<Collection<P>, Collection<R>> dataQueryFunction,
                                           Consumer<Collection<R>> dataProcessConsumer,
                                           Function<Collection<R>, Collection<P>> extractParamFunction,
                                           Collection<P> startParam) {
    Collection<R> dataList;
    do {
        log.info("loop utils param is {}", JSONUtil.toJsonStr(startParam));
        dataList = dataQueryFunction.apply(startParam);
        if (CollUtil.isNotEmpty(dataList)) {
            dataProcessConsumer.accept(dataList);
            startParam = extractParamFunction.apply(dataList);
        }
    } while (CollUtil.isNotEmpty(dataList));

    log.info("processData exist start param is {}", startParam);
}

使用代码如下

@Override
public void initAncestor() {
   // 先查出第一批根部门
   List<DeptDO> deptDOList = deptMapper.selectListByParentId(Lists.newArrayList(DeptDO.PARENT_ID_ROOT));
   List<Long> parentIds = LambdaUtils.mapToList(deptDOList, DeptDO::getId);

   // 先处理根部门
   deptMapper.update(new LambdaUpdateWrapper<DeptDO>()
           .set(DeptDO::getParentIds, DeptDO.PARENT_ID_ROOT_STR)
           .eq(DeptDO::getParentId, 0L));

   // 循环处理
   DataLoopUtil.processDataBatch(
           getListDeptFn(),
           getDeptConsumer(),
           getParamExtractFn(),
           parentIds);
}

////////////////////////// 下面是参数获取方法 //////////////////////////

private Function<Collection<DeptDO>, Collection<Long>> getParamExtractFn() {
   return deptList -> LambdaUtils.mapToSet(deptList, DeptDO::getId);
}

private Function<Collection<Long>, Collection<DeptDO>> getListDeptFn() {
   return parentIds -> deptMapper.selectListByParentId(parentIds);
}

private Consumer<Collection<DeptDO>> getDeptConsumer() {
   return deptList -> {
       if (CollUtil.isEmpty(deptList)) {
           return;
       }
       // 批量查询父级部门
       Set<Long> parentIds = LambdaUtils.mapToSet(deptList, DeptDO::getParentId);
       List<DeptDO> parentDeptList = deptMapper.selectBatchIds(parentIds);
       Map<Long, DeptDO> parentMap = LambdaUtils.toMap(parentDeptList, DeptDO::getId);

       // 开始处理
       Map<Long, List<DeptDO>> deptMap = LambdaUtils.groupList(deptList, DeptDO::getParentId);
       deptMap.forEach((parentId, list) -> {
           DeptDO parent = parentMap.get(parentId);
           if (parent == null) {
               log.info("parent dept not exists, id {}", parentId);
               return;
           }
           list.forEach(dept -> deptMapper.update(new LambdaUpdateWrapper<DeptDO>()
                   .set(DeptDO::getParentIds, parent.getParentIds() + "," + parent.getId())
                   .eq(DeptDO::getId, dept.getId())));
       });
   };
}

标签:Function,startParam,处理,getId,dataList,循环,param,轮子,DeptDO
From: https://www.cnblogs.com/tailife/p/18451630

相关文章

  • Kafka的常见问题及解决方案:轻松驾驭流处理的利器
    ApacheKafka,作为一个分布式的流处理平台,因其高吞吐量和横向扩展能力而受到广泛欢迎。然而,在日常使用中,Kafka用户常常面临一些挑战。本文将深入探讨Kafka中的常见问题以及高效解决方案,帮助您更好地驾驭这一强大工具。1. 高延迟问题问题描述:在流数据处理时,用户常常发现数......
  • 图像处理软件Adobe Photoshop(ps)软件下载安装(附安装包)
    目录软件简介下载链接功能特点软件简介AdobePhotoshop,简称“PS”,是由AdobeSystems公司开发和发行的一款功能强大的图像处理软件。自1988年首次发布以来,Photoshop已经成为图像处理领域的标杆产品,广泛应用于平面设计、摄影后期、网页设计、视频制作、出版印刷等多个领域......
  • 五款倾斜摄影与三维数据处理工具介绍:GISBox、Cesiumlab、OSGBLab、灵易智模、倾斜伴侣
    随着三维数据处理技术的广泛应用,尤其是在城市规划、地理信息系统(GIS)、工程监测等领域,处理倾斜摄影、三维建模以及大规模数据管理的需求日益增加。以下是五款我精心挑选的倾斜摄影和三维数据处理工具——GISBox、Cesiumlab、OSGBLab、灵易智模和倾斜伴侣,本文将详细介绍它们的功能、......
  • SQL批处理脚本的使用与优化
    在现代数据库管理中,批处理脚本的使用已经成为提高效率和减少重复工作的关键工具。本文将详细介绍SQL批处理脚本的使用方法、优化策略以及在不同数据库系统中的应用。1.批处理的基本概念批处理是指将多个SQL语句组合在一起执行的方式,这种方式可以显著提高数据库操作的效率。通......
  • 网站建设中遇到被恶意篡改的情况如何处理
    当网站遭遇恶意篡改时,可以按照以下步骤进行处理:立即停止服务立即停止网站服务,避免恶意内容继续传播。备份当前数据在修改任何东西之前,先备份当前服务器上的所有文件和数据库,以便后续恢复或分析。检查日志文件查看服务器日志、Web访问日志以及应用程序日志,寻找可......
  • Java中的任务超时处理
    Java中的任务超时处理综述任务超时处理是编程世界中一个不可或缺且常见的处理机制,特别是在进行耗时任务时,如网络请求,数据库查询,大规模数据处理等场景。在这些情况下,为了防止任务因各种不可预测的因素(如网络延迟,服务器响应超时,数据量过大等)而无休止地占用宝贵的系......
  • Python 循环语句的高级应用与技巧
    在Python中,循环语句是实现重复操作的重要工具。以下将深入探讨一些高级的应用和技巧:for循环的高级用法#遍历字典的键值对my_dict={'a':1,'b':2,'c':3}forkey,valueinmy_dict.items():print(f'Key:{key},Value:{value}')#遍历多个序列names=['Alice',......
  • 信息学奥赛复赛复习14-CSP-J2021-03网络连接-字符串处理、数据类型溢出、数据结构Map
    PDF文档公众号回复关键字:202410071P7911[CSP-J2021]网络连接[题目描述]TCP/IP协议是网络通信领域的一项重要协议。今天你的任务,就是尝试利用这个协议,还原一个简化后的网络连接场景。在本问题中,计算机分为两大类:服务机(Server)和客户机(Client)。服务机负责建立连接,客户机......
  • 公司网站出现乱码怎么处理
    处理公司网站出现乱码的问题,可以按照以下步骤进行:检查字符编码设置:确认网页和数据库的字符编码是否一致,通常推荐使用 UTF-8 编码。审查HTTP响应头:确保服务器正确设置了 Content-Type 响应头,指明了正确的字符集。查看HTML元信息:在HTML文档中 <head> 部分检查......
  • Python 循环语句的高级应用与深度探索
    在Python中,循环语句是实现重复操作的重要工具。本文将深入探讨Python循环语句的高级应用。 for 循环的高级用法#遍历字典并同时获取键和值my_dict={'a':1,'b':2,'c':3}forkey,valueinmy_dict.items():print(f'Key:{key},Value:{value}')#......