集合分片处理

374 阅读2分钟

前言

在日常开发中,集合分批次处理、按指定数量批量入库是常见操作,如何方便快捷的使用呢?

本文章介绍了四种解决方案,并最终完成最简单最快捷的策略。

如下代码,减少自己操作:

一、利用List循环赋值

  • 此方法非常笨拙,且速度很慢;不推荐使用

        
        // 需要转群主的客户群ID列表。取值范围: 1 ~ 100
        List<String> chatIds = new ArrayList<>();
        int a = 0;
        for (int i = 0; i < chatIds.size(); i++) {
    
            a++;
            if (a == 99) {
              
            }
        }
        // 剩余不足100的进行再次处理
        if (a != 0) {
           
        }
    复制代码
    

二、利用List截取

  • 此方法存在一定冗余操作,且速度慢;不推荐使用
    List<String> collect = new ArrayList();
    int listSize = collect.size();
    //一次处理得数量 企业微信一次最多支持100个
    int subSize = 100;
    int toIndex = subSize;
    //作用为toIndex最后没有10条数据则剩余几条newList中就装几条
    for (int i = 0; i < collect.size(); i += subSize) {
        if (i + subSize > listSize) {
            toIndex = listSize - i;
        }
        List<String> list = collect.subList(i, i + toIndex);
        //一次批处理
        //doBatchUser(list,"");
    }
复制代码

三、利用CollUtil.sub方法

  • CollUtil.sub方法对集合切片,其他类型的集合会转换成List,封装List.subList方法,自动修正越界等问题,完全避免IndexOutOfBoundsException异常;推荐

        // 客户的external_userid列表,最多一次转移100个客户
        int size = batchVO.getChatId().size();
        int endIndex = 100;
        for (int i = 0; i < size; i += 100) {
            // 剩余不足100的进行再次处理
            if (i + 100 > size) {
                endIndex = size - i;
            }
            List<String> list = CollUtil.sub(batchVO.getChatId(), i, i + endIndex);
            request.setExternalUserid(list);
            resignedTransferService.transferCustomer(request);
        }
    复制代码
    

四、使用Lists.partition切分性能优化 

  • Lists.partition 是通过提供一层抽象来实现分片的,通过 get 返回一个子列表,子列表具体有 subList 来实现,速度快,代码简洁;非常推荐
  1. 依赖pom

        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1.1-jre</version>
        </dependency>
    复制代码
    

   2. 代码

// list 分片数量
List<List<MarketingResultBatch>> groupList = Lists.partition(updatePushResultList,100);
groupList.stream().forEach(list->{
    // 批量入库
    updateMarketingResultBatch1000(list,updatedTime);
});
复制代码

   3. 注意事项

List<List<TreasureIntegrationVo>> resultPartition = Lists.partition(list, 500) 之后再对 list 进行 clear 操作,resultPartition也会被清空;

后来才发现谷歌它最终会调用 list.subList

subList 执行结果是获取 ArrayList 的一部分,返回的是 ArrayList 的部分视图;

对子集合的操作会反映到原集合, 对原集合的操作也会影响子集合。