Java List分批处理

工作中经常遇到分批处理的问题,比如将一个List列表中的数据分批次保存至数据库中。如果列表中数据条目很大,比如1000万条以上,mysql中 max_allowed_packet 所能允许的最大数据包量不支持如此大的数据量,这种情况下一次性保存处理就会出现保存失败。另外,过大的数据条目数量,在保存时也会导致性能下降。为此手动批量处置就成为了一种必须。这里给出分批处理的代码,方便以后直接使用。

package com.lunyu.algorithm.service.base;

import com.google.common.collect.Lists;
import java.util.List;

/**
 * @author lunyu
 * @since 2021/1/25
 */
public class BaseService {

  /**
   * 每个批次数据条目
   */
  private static final int BATCH_SIZE = 10;

  public static void main(String[] args){

    List<Integer> list = Lists.newArrayList();
    for (int i = 0; i < 23; i++){
      list.add(i + 1);
    }

    // 获取执行的轮次
    int round = (list.size() - 1) / BATCH_SIZE;

    for (int i = 0; i <= round; i++){
      // 求每个批次起始位置
      int fromIndex = i * BATCH_SIZE;
      int toIndex = (i + 1) * BATCH_SIZE;
      // 如果是最后一个批次,则不能越界
      if (i == round){
        toIndex = list.size();
      }

      List<Integer> subList = list.subList(fromIndex, toIndex);

      // TODO: 对subList执行进一步要做的操作
      System.out.println("轮次:" + i);
      subList.forEach(e -> {
        System.out.print(e + ",");
      });
      System.out.println();
    }
  }

}

 这里有三个个注意的点,

第一, 获取轮次使用 (list.size() - 1) / BATCH_SIZE ,这是为了方便将属于同一个批次的数据放在该批次下。以代码为例,如果恰好有10个元素 1-10 (对应的坐标 0-9 ),我们要把它们放置在同一个批次下, BATCH_SIZE = 10; ,那么 list.size() - 1 = 9 ,恰好可以使最后一个元素和前面所有的元素都在一个批次下,这个批次等于 0。

第二,循环的轮次为  i <= round; ,这时为了保证所有的批次都能访问到。

第三, if (i == round) ,要保证最后一个批次的数据,在获取时不能数组越界。为了代码美观, toIndex 可以用三元表达式统一起来,写做:

int toIndex = (i < round) ? ((i + 1) * BATCH_SIZE) : list.size();

posted on 2021-01-26 00:36  论语  阅读(2666)  评论(0编辑  收藏  举报

导航