• Java 使用ListUtils对List分页处理


    背景分析

      工作中,经常遇到需要用Java进行分页处理数据,例如把1000万条Excel数据写入MySQL数据库,如果把这1000w数据一股脑的丢给MySQL,保证把数据库玩完,故需要批量写入,如每批次写入500条。这时候就可以使用ListUtils.partition了。

    maven坐标

      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();
            }
        }
    

    小结

       你如果对于如何分页不熟练,使用如上分页技术进行处理,是不是很简单?如果你有更轻巧的方法,欢迎留言评论。

  • 相关阅读:
    IO流之File类
    CPU单核多核区别【转载】
    [转载] MySQL的四种事务隔离级别
    事务的四大特性,以及隔离级别
    [转载] spring aop 环绕通知around和其他通知的区别
    [转载] Spring框架——AOP前置、后置、环绕、异常通知
    spring框架 AOP核心详解
    汇编语言--操作数的寻址方式(三)
    汇编语言--CPU资源和存储器(二)
    汇编语言学习--基础知识(一)
  • 原文地址:https://www.cnblogs.com/east7/p/15876727.html
Copyright © 2020-2023  润新知