工作中經常遇到分批處理的問題,比如將一個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) ,要保證最后一個批次的數據,在獲取時不能數組越界。
