赞
踩
工作中,经常遇到需要用Java进行分页处理数据,例如把1000万条Excel数据写入MySQL数据库,如果把这1000w数据一股脑的丢给MySQL,保证把数据库玩完,故需要批量写入,如每批次写入500条。这时候就可以使用ListUtils.partition了。
commons-collections4和Guava两个jar包的坐标如下:
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-collections4</artifactId>
- <version>4.4</version>
- </dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>31.0.1-jre</version>
- </dependency>
批处理List
基于commons-collections4和Guava两个jar包,对java.util.List中海量数据进行分批处理的逻辑如下所示,请求参数都是传入List和每页处理的数据量:
- public static void main(String[] args) {
- List<String> list =new ArrayList<>();
- list.add("a");
- list.add("b");
- list.add("c");
- list.add("d");
- list.add("Wiener");
- batchDealData(list, 3);
- batchDealByGuava(list, 3);
- }
-
- private static void batchDealData (List data, int batchNum) {
-
- // commons-collections4
- List<List<String>> partitions = ListUtils.partition(data, batchNum);
- partitions.stream().forEach(sublist -> {
- System.out.println(sublist);
- });
- }
- private static void batchDealByGuava (List data, int batchNum) {
- // guava
- List<List<String>> partitions = Lists.partition(data, batchNum);
- partitions.stream().forEach(sublist -> {
- System.out.println(sublist);
- });
- }
这种处理方法相对于手动分页,其优点显而易见,既可以降低代码复杂度,又可以提高开发效率。小编在《Java 使用线程池分批插入或者更新数据》中,介绍了一种通用分页方式,略显复杂,下面基于commons-collections4,优化其中的分页策略,代码如下:
- private void batchDeal(List<Object> data, int batchNum) throws InterruptedException {
- if (CollectionUtils.isEmpty(data)) {
- return;
- }
- // 使用 ListUtils.partition分页
- List<List<Object>> newList = ListUtils.partition(data, batchNum);
- // 计算总页数
- int pageNum = newList.size();
- ExecutorService executor = Executors.newFixedThreadPool(pageNum);
- try {
- CountDownLatch countDownLatch = new CountDownLatch(pageNum);
- for (int i = 0; i < pageNum; i++) {
- ImportTask task = new ImportTask(newList.get(i), countDownLatch);
- executor.execute(task);
- }
- countDownLatch.await();
- log.info("数据操作完成!可以在此开始其它业务");
- } finally {
- // 关闭线程池,释放资源
- executor.shutdown();
- }
- }
- // 无改动
- class ImportTask implements Runnable {
- private List list;
- private CountDownLatch countDownLatch;
-
- public ImportTask(List data, CountDownLatch countDownLatch) {
- this.list = data;
- this.countDownLatch = countDownLatch;
- }
-
- @Override
- public void run() {
- if (null != list) {
- // 业务逻辑,例如批量insert或者update
- log.info("现在操作的数据是{}", list);
- }
- // 发出线程任务完成的信号
- countDownLatch.countDown();
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。