前言
在日常开发中,集合分批次处理、按指定数量批量入库是常见操作,如何方便快捷的使用呢?
本文章介绍了四种解决方案,并最终完成最简单最快捷的策略。
如下代码,减少自己操作:
一、利用List循环赋值
-
此方法非常笨拙,且速度很慢;不推荐使用
List<HandoverExternalChat> externalUser = externalChat.list(queryWrapper); // 客户的external_userid列表,最多一次转移100个客户 List<String> externalUserIds = new ArrayList<>(); // 需要转群主的客户群ID列表。取值范围: 1 ~ 100 List<String> chatIds = new ArrayList<>(); // 初始化群分配 List<ResignedTransferGroupResponse.FailedChat> list = new ArrayList<>(); int a = 0; for (int i = 0; i < externalUser.size(); i++) { externalUserIds.add(externalUser.get(i).getExternalUserid()); chatIds.add(externalUser.get(i).getChatId()); a++; if (a == 99) { // 分配离职成员的客户 request.setExternalUserid(externalUserIds); resignedTransferService.transferCustomer(request); // 分配离职成员的客户群 transferGroupRequest.setChatIdList(chatIds); ResignedTransferGroupResponse result = resignedTransferService.groupChatTransfer(transferGroupRequest); list.addAll(result.getFailedChatList()); a = 0; externalUserIds = new ArrayList<>(); chatIds = new ArrayList<>(); } } // 剩余不足100的进行再次处理 if (a != 0) { // 分配离职成员的客户 request.setExternalUserid(externalUserIds); resignedTransferService.transferCustomer(request); // 分配离职成员的客户群 transferGroupRequest.setChatIdList(chatIds); ResignedTransferGroupResponse result = resignedTransferService.groupChatTransfer(transferGroupRequest); list.addAll(result.getFailedChatList()); }
二、利用List截取
-
此方法存在一定冗余操作,且速度慢;不推荐使用
// 客户的userid列表,最多一次转移100个客户 List<ExternalContactBehaviorData> list = new ArrayList<>(); int a = 0; int b = 0; for (int i = 1; i < userList.size() + 1; i++) { b++; if (b == 99) { request.setUserId(ListUtil.sub(userList, a, i + a)); ExternalContactBehaviorDataResponse userBehaviorData = externalContactService.getUserBehaviorData(request); if (!userBehaviorData.isOk()) { throw new WecomCustomerException(userBehaviorData.getErrMsg()); } list = userBehaviorData.getBehaviorData(); a = i; b = 0; } } // 剩余不足100的进行再次处理 if (b != 0) { request.setUserId(ListUtil.sub(userList, a, userList.size())); ExternalContactBehaviorDataResponse userBehaviorData = externalContactService.getUserBehaviorData(request); if (!userBehaviorData.isOk()) { throw new WecomCustomerException(userBehaviorData.getErrMsg()); } list.addAll(userBehaviorData.getBehaviorData()); }
三、利用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 来实现,速度快,代码简洁;非常推荐
-
依赖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 的部分视图;
对子集合的操作会反映到原集合, 对原集合的操作也会影响子集合。