Java中的批量操作实现

package com.h.collection;

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

/**
 * Created by John on 2017/9/11.
 */
public class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");
        list.add("3");
        String str = String.join(",",list);
        System.out.println(str);
    }

    /**
     * 批量查询/插入
     * 查询数据量非常大时,分批查,减轻数据库一次查询的压力
     * @param userIdList 用户ID的集合
     */
    public static void batchSelect(List<String> userIdList){
        int totalSelectCount = userIdList.size();//总查询量
        int perSelectCount = 1000;//每次查询的数据量
        int index = 0;//查询中间量
        List<String> selectList = null;
        List<User> userList = null;
        while (totalSelectCount > index){
            int selectCount = Math.min(totalSelectCount,index + perSelectCount);
            selectList = userIdList.subList(index,selectCount);//查询范围[index,selectCount-1];
            userList = userServiceImpl.batchSelectUserById(String.join(",",selectList));
            for (User user:userList){
                //其他set操作,继续封装
            }
            index += perSelectCount;
        }
    }

    /**
     * 批量查询/插入
     * 查询数据量非常大时,分批查,减轻数据库一次查询的压力
     * @param userIdList
     */
    public static void batchSelect2(List<String> userIdList){
        int totalSelectCount = userIdList.size();//总查询量
        int perSelectCount = 1000;//每次查询的数据量
        int cycleCount = totalSelectCount % perSelectCount == 0 ? totalSelectCount/perSelectCount:totalSelectCount/perSelectCount + 1;//循环查询次数
        List<String> selectList = null;
        List<User> userList = null;
        for (int i=0;i<cycleCount;i++){
            //[0,999] [1000,1999] ... 这里用到了分页的思想
            selectList = userIdList.subList(i*perSelectCount,(i+1)*perSelectCount > totalSelectCount ? totalSelectCount:(i+1)*perSelectCount);//[,)
            userList = userServiceImpl.batchSelectUserById(String.join(",",selectList));
            for (User user:userList){
                //其他set操作,继续封装
            }
        }
    }
}

package com.h.java8;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by John on 2018/9/30.
 * 批量操作模板类,如批量查询/插入
 */
public abstract class BatchOperateUtil<T> { //T为操作的实际元素
    //需要操作的数据源
    private List<T> sourceList;

    //批量操作的临界值(每次操作量)
    private int threshold;

    public BatchOperateUtil setSourceList(List<T> sourceList){
        this.sourceList = sourceList;
        return this;
    }

    public BatchOperateUtil setThreshold(int threshold){
        this.threshold = threshold;
        return this;
    }

    public void batchOperate() {
        int size = sourceList.size();
        int fromIndex = 0;
        List<T> list = null;
        int toIndex = 0;
        while (size > fromIndex){
            toIndex = Math.min(size,fromIndex + threshold);
            //注意截取子串时索引越界
            list = sourceList.subList(fromIndex,toIndex);
            operate(list);
            fromIndex += threshold;
        }
    }

    /**
     * 分页的思想实现批量操作
     */
    public void batchOperate2(){
        //总操作量
        int size = sourceList.size();
        //循环操作次数
        int cycleCount = size % threshold == 0 ?  size/threshold :  size/threshold + 1;
        List<T> list = null;
        for (int i=0;i<cycleCount;i++){
            //注意截取子串时索引越界
            list = sourceList.subList(i*threshold,Math.min((i+1)*threshold,size));
            operate(list);
        }
    }

    /**
     * 使用java8的流式操作截取子串(不需要考虑越界问题)
     */
    public void batchOperate3(){
        int size = sourceList.size();
        int fromIndex = 0;
        List<T> list = null;
        while (size > fromIndex){
            list = sourceList.stream().skip(fromIndex).limit(threshold).collect(Collectors.toList());
            operate(list);
            fromIndex += threshold;
        }
    }

    /**
     * 具体的操作实现
     * @param data
     */
    public abstract void operate(List<T> data);
}
package com.h.java8;

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

/**
 * Created by John on 2018/9/23.
 */
public class TestMain {

    public static void main(String[] args) {
        List<String> sourceList = new ArrayList<>();
        sourceList.add("a");
        sourceList.add("b");
        sourceList.add("c");
        sourceList.add("d");
        sourceList.add("e");

        BatchOperateUtil<String> operateUtil = new BatchOperateUtil<String>() {
            @Override
            public void operate(List<String> data) {
                System.out.println(data);
                //可以是批量插入或查询的具体操作
            }
        }.setSourceList(sourceList).setThreshold(3);
        operateUtil.batchOperate();
        System.out.println("==============");
        operateUtil.batchOperate2();
        //使用java8的流式操作
        System.out.println("==============");
        operateUtil.batchOperate3();
    }
}

使用Lambda表达式替代上面的模版方法

public class BatchOperateUtil<T> { //T为操作的实际元素
    //需要操作的数据源
    private List<T> sourceList;

    //批量操作的临界值
    private int threshold;

    public BatchOperateUtil setSourceList(List<T> sourceList){
        this.sourceList = sourceList;
        return this;
    }

    public BatchOperateUtil setThreshold(int threshold){
        this.threshold = threshold;
        return this;
    }

    public void batchOperate(Consumer<List<T>> operater) {
        int size = sourceList.size();
        int fromIndex = 0;
        List<T> list = null;
        while (size > fromIndex){
            list = sourceList.stream().skip(fromIndex).limit(threshold).collect(Collectors.toList());
            operater.accept(list);
            fromIndex += threshold;
        }
    }
}
	    List<String> list = Arrays.asList("a","b","c","d","e");
        BatchOperateUtil<String> batchOperateUtil = new BatchOperateUtil<>();
        batchOperateUtil.setSourceList(list).setThreshold(3).batchOperate(l -> {
            System.out.println(l);//模拟数据库的批量插入或查询操作
        });
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值