List 分段批量处理数据与Database交互或接口调用

目录

1、使用场景

2、代码实现        

3、原理分析及总结

4、实战代码

5、参考文章


1、使用场景

        我们实际工作之中,可能针对返回的数据进行分段、批量提交到数据库插入记录(如Excel导入多条记录)。因为我们后端数据库不可能一次性处理以1000条或者更多记录;于是需要针对导入的记录进行分段批量处理。最近我在对接用户中心的时候,有一个通过Excel批量导入用户的功能;但是用户中心提供的接口每次仅仅接收50条记录的处理。于是我需要针对Excel读取的大量记录进行分段分批的处理记录。保证每次提交到用户中心接口的数据是小于等于50条记录的。

2、代码实现        

import java.util.ArrayList;
import java.util.List;

/**
 * @Classname SegmentedBatchList
 * @Description List 的分段处理
 * @Date 2020/3/22 11:51
 * @Created by jianxiapc
 */
public class ListSegmentedBatch {

    public static void main(String[] args) {
        List<Integer> dataList = new ArrayList<Integer>();
        for(int i = 1; i <=132; i++){
            dataList.add(i);
        }
        //segmentedBatchSubListClearMethod(dataList);
        generalSegmentedBatchSubList(dataList);
    }

    /**
     * 使用 subList clear方式删除已经使用使用过的list 元素
     * @param dataList
     */
    public static  void segmentedBatchSubListClearMethod(List<Integer> dataList){
        //分批处理
        if (dataList.size() > 0) {
            //限制条数
            int pointsDataLimit = 10;
            int size = dataList.size();
            //判断是否有必要分批
            if (pointsDataLimit < size) {
                //分批数
                int part = size / pointsDataLimit;
                System.out.println("共有 : " + size + "条,!" + " 分为 :" + part + "批");
                for (int i = 0; i < part; i++) {
                    //1000条
                    List<Integer> listPage = dataList.subList(0, pointsDataLimit);
                    System.out.println("clearMethod: "+listPage);
                    //剔除
                    dataList.subList(0, pointsDataLimit).clear();
                }
                //此处处理整页后剩余部分
                if (!dataList.isEmpty()) {
                    //表示最后剩下的数据
                    System.out.println("clearMethod: "+dataList);
                }
            } else {
                System.out.println(dataList);
            }
        } else {
            System.out.println("没有数据!!!");
        }
    }

    /**
     * 普通分段处理list方法
     * @param dataList
     */
    public  static  void generalSegmentedBatchSubList(List<Integer> dataList){
        int perMaxDealCount=10,index=1;
        int wholePage=dataList.size()/perMaxDealCount;
        int times=dataList.size()%perMaxDealCount==0?(wholePage):(wholePage+1);
        do{
            List<Integer> pageDealDataList=new ArrayList<Integer>();
            // pageDealDataList是分段处理逻辑的参数
            int startIndex=(index-1)*perMaxDealCount;
            //此处需要注意 list.subList(int fromIndex, int toIndex)  返回list中指定下标的元素组成的list集合,左闭右开
            int endIndex=index*perMaxDealCount;
            if(index==times){
                pageDealDataList=dataList.subList(startIndex, dataList.size());
                System.out.println("general: "+pageDealDataList);
            }else{
                pageDealDataList=dataList.subList(startIndex, endIndex);
                System.out.println("general: "+pageDealDataList);
            }
            index++;
        }
        while (index<=times);
    }
}

3、原理分析及总结

       本实现方法使用List的 sublist方法来实现了 数据分段分批处理,注意事项:

(1)、List subList(int fromIndex, int toIndex)  返回list中指定下标的元素组成的list集合,左闭右开

参数: 
  fromIndex - subList 的低端(包括) 
  toIndex - subList 的高端(不包括) 

(2)、注意点

扫描二维码关注公众号,回复: 13465572 查看本文章

    返回的新的集合指向原有集合,修改新的集合会影响原有集合的内容.

(3)、决解方案

    3.1、新建一个新的集合

            ArrayList<String> realList = new ArrayList<String>(list.subList( fromIndex,  toIndex)); 操作realList不会影响原有list.

    3.2、添加到新的集合中

           ArrayList<String> newList = new ArrayList<String>();

           newList.addAll(list.subList( fromIndex,  toIndex));

           操作newList不会影响原有list.

   (4)、可以每次使用sublist clear 方法清除以前使用过的分段数据

  上述代码主要目的是通过一个基本示例;让我们明白如何在实际项目之中实现基本的List 分段批量(SegmentedBatch)操作。

4、实战代码

	public Map<String,Object> executeBatchImportUserByExcel(PermissionUser currentUser,String operatorUserKey, 
			List<PermissionUser> importExcelUserList) {
		
		int perMaxDealCount=50,index=1;
		int wholePage=importExcelUserList.size()/perMaxDealCount;
		int times=importExcelUserList.size()%perMaxDealCount==0?(wholePage):(wholePage+1);
		Map<String,Object> resultMap=new HashMap<String,Object>();
		String operatorResult="0";
		List<Map<String,String>> batchImportUserStatusList=new ArrayList<Map<String,String>>();
		do  {
			List<PermissionUser> pageDealDataUserList=new ArrayList<PermissionUser>();
			// pageDealDataList是分段处理逻辑的参数
			int startIndex=(index-1)*perMaxDealCount;
			//此处需要注意 list.subList(int fromIndex, int toIndex)  返回list中指定下标的元素组成的list集合,左闭右开
			int endIndex=index*perMaxDealCount;
			if(index==times){
				pageDealDataUserList=importExcelUserList.subList(startIndex, importExcelUserList.size());
			}else{
				pageDealDataUserList=importExcelUserList.subList(startIndex, endIndex);
			}
			// 调用用户中心接口 以每50条记录上传数据到 用户中心去
			Map<String, Object> paramMap=new HashMap<String,Object>();
			//此处处理主要是针对用户中心所需的用户信息 整合为map list进行上传
			Map<String, Object> ucUserMap=null;
			List<Map<String, Object>> pageDealDataList=new ArrayList<Map<String, Object>>();			
			for(PermissionUser itemUser:pageDealDataUserList) {
				ucUserMap=new HashMap<String,Object>(7);
				ucUserMap.put("user_account", itemUser.getLoginName());
				ucUserMap.put("password", Constant.USER_PASSWORD);
				ucUserMap.put("name",itemUser.getRealName());
				ucUserMap.put("sex", itemUser.getSexType()=="0"?1:2);
				ucUserMap.put("phone",itemUser.getTelephone());
				ucUserMap.put("avatar_url",itemUser.getPhotoUrl());
				ucUserMap.put("role", 1);
				//设置用户名信息到list
				Map<String,String> userLoginNameMap=new HashMap<String,String>(5);
				userLoginNameMap.put("loginName", itemUser.getLoginName());
				batchImportUserStatusList.add(userLoginNameMap);
				pageDealDataList.add(ucUserMap);
			}
			JSONArray dataJsonArray = (JSONArray)JSON.toJSON(pageDealDataList);
			String dataJson=dataJsonArray.toString();
			logger.info("批量处理 注册用户的请求:\n"+dataJson);
			paramMap.put("userKey", operatorUserKey);
			paramMap.put("data", dataJsonArray);
			//从json之中获得获得信息
			JSONObject responseResultJson=administratorOperateUserService.batchRegister(paramMap);
			JSONObject responseBodyJson=responseResultJson.getJSONObject("responseBody");
			String userCenterExceptionMsg=responseResultJson.getString("userCenterExceptionMsg");
			//此处处理不一样 需要遇见异常直接退出循环
			if(!"no".equals(userCenterExceptionMsg)){
				logger.info("userLogin==> userCenterExceptionMsg: {}", userCenterExceptionMsg);
				resultMap.put("success","-1");
				resultMap.put("message",userCenterExceptionMsg);
				return resultMap;
			}
			logger.info("requestResultJson :\n"+responseBodyJson.toJSONString());
			String statusNum=responseBodyJson.get("status").toString();
			String message=responseBodyJson.get("msg").toString();
			if("200".equals(statusNum)) {
				//获得注册到用户中心后的 返回的数据给予前端页面提醒
				JSONArray batchRegisterResultData =responseBodyJson.getJSONArray("data");
				for(int i=0;i<batchRegisterResultData.size();i++){
					JSONObject itemJson=batchRegisterResultData.getJSONObject(i);
					String registerStatus=itemJson.get("status").toString();
					String userAccount=itemJson.get("user_account").toString();
					//是否注册过其他app 1 已注册别的app  0  没有
					String isRegisterOtherApp=itemJson.get("is_register_other_app").toString();
					//设置用户名导入状态到list
					Map<String,String> userStatusMap=batchImportUserStatusList.get(i);
					if("注册成功".equals(registerStatus)){
						userStatusMap.put("registerStatusFlag","0");
					}else if("用户名已存在".equals(registerStatus)){
						userStatusMap.put("registerStatusFlag","2");
						Iterator<PermissionUser> userIterator=pageDealDataUserList.iterator();
						while(userIterator.hasNext()){
							PermissionUser user= userIterator.next();
							String loginName=user.getLoginName();
							if(userAccount.equals(loginName)){
								userIterator.remove();
							}
						}
					}else if("手机号已存在".equals(registerStatus)){
							userStatusMap.put("registerStatusFlag","3");
							Iterator<PermissionUser> userIteratorTel=pageDealDataUserList.iterator();
							while(userIteratorTel.hasNext()){
								PermissionUser user= userIteratorTel.next();
								String loginName=user.getLoginName();
								if(userAccount.equals(loginName)){
									userIteratorTel.remove();
								}
							}
					}else{
						userStatusMap.put("registerStatusFlag","1");
					}
					if("1".equals(isRegisterOtherApp)){
						userStatusMap.put("isRegisterOtherAppText","该用户注册过的其他产品,请使用原密码登录");
					}else{
						userStatusMap.put("isRegisterOtherAppText","该用户为新注册系统用户");
					}
					userStatusMap.put("isRegisterOtherApp",isRegisterOtherApp);
					userStatusMap.put("registerStatus",registerStatus);
				}
				logger.info("第"+index+" 批次 =====> 批量处理注册用户上传用户中心  成功 ! "+pageDealDataUserList.size()+" 记 录");				
				operatorResult="0";
				resultMap.put("message","第"+index+" 批次 批处理注册用户到用户中心 共计 批处理 "+pageDealDataUserList.size()+" 记 录");
				// 然后导入数据到自己有系统之中
				permissionUserService.saveAllUser(currentUser,pageDealDataUserList);
				//导入完毕后  更新 loginid和status
				batchUpdateSyncWdyEduLoginIdAndStatus(responseBodyJson);
				
			}else {
				logger.error("第"+index+" 批次 =====> 批量处理注册用户上传用户中心  有部分数据失败!");
				operatorResult="-1";
				resultMap.put("success",operatorResult);
				resultMap.put("message",message);
				return resultMap;
			}
			//遍历当前的值是否正确
			//System.out.println("第"+index+"轮:>>"+pageDealDataList.size());		
			importExcelUserList.removeAll(pageDealDataList);			
			//System.out.println("当前剩余集合长度:>>"+importExcelUserList.size());	
			index++;
		}
		while (index<=times);	
		resultMap.put("success",operatorResult);
		resultMap.put("batchImportUserStatusList",batchImportUserStatusList);
		//如果没有任何问题返回最后一个批次结果信息
		return resultMap;
	}	

5、参考文章

java如何截短一个List以及List.subList()方法的坑

java List(分割)分批处理

猜你喜欢

转载自blog.csdn.net/jianxia801/article/details/105070101