博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
将List按照指定大小等分的几种实现方式和效率对比及优化
阅读量:6227 次
发布时间:2019-06-21

本文共 4185 字,大约阅读时间需要 13 分钟。

  今天碰到一个需求,定时任务,批量从表里取数据并做一些其他操作然后再存表,每次取1000条,由于计算过程比较耗时所以要起多个线程同时跑,需要将List按照指定大小等分,如每100条数据起一个线程,若最后剩余一份不到100,也放到一个线程里,网络上的实现方法有很多,我测试之后理出三种相对比较好的实现方法,如下:

1 /*第一种方法 思路比较简单,遍历list,将元素添加到subList, 2 *每当i到pageSize的时候,将subList添加到listArray并新建,subList 3 */ 4 public static 
List
> splitList1(List
list, int pageSize) { 5 6 List
> listArray = new ArrayList
>(); 7 8 List
subList = null; 9 10 for (int i = 0; i < list.size(); i++) {11 12 if (i % pageSize == 0) {13 14 subList = new ArrayList
();15 16 listArray.add(subList);17 18 }19 20 subList.add(list.get(i));21 22 }23 24 return listArray;25 26 }
/*第二种方法 思路和方法1差不多,遍历list,将元素添加到subList,*当subList的size等于pageSize的时候,将subList添加到listArray并新建subList*/public static 
List
> splitList2(List
list, int pageSize) { List
> listArray = new ArrayList
>(); ArrayList
subList = new ArrayList
(); for (T x : list) { subList.add(x); if (pageSize == subList.size()) { listArray.add(subList); subList = new ArrayList
(); } } if (0 != subList.size()) { listArray.add(subList); } return listArray;}
/*第三种方法,用到了java list自带的方法subList,*先判断list的size<pageSize的情况,然后利用subList方法循环切块*/public static 
List
> splitList3(List
list, int pageSize) { List
> listArray = new ArrayList
>(); if (list != null && pageSize > 0) { int listSize = list.size(); if (listSize <= pageSize) { listArray.add(list); return listArray; } int batchSize = listSize / pageSize; int remain = listSize % pageSize; for (int i = 0; i < batchSize; i++) { int fromIndex = i * pageSize; int toIndex = fromIndex + pageSize; listArray.add(list.subList(fromIndex, toIndex)); } if (remain > 0) { listArray.add(list.subList(listSize - remain, listSize)); } } return listArray;}

  我从list的subList方法中得到灵感,也实现了一种方式,可读性稍好一些,如下:

/*我的思路也比较简单,就是遍历加切块,*若toIndex大于list的size说明已越界,需要将toIndex设为list的size值*/public static 
List
> splitList4(List
list, int pageSize) { List
> listArray = new ArrayList
>(); for (int i = 0; i < list.size(); i+=pageSize) { int toIndex = i + pageSize>list.size()?list.size():i+pageSize; listArray.add(list.subList(i, toIndex)); } return listArray;}

  以上四种方法经过测试都可实现功能,如果List的size比较小,几十,几百,应该效率都差不多,那如果list的size很大,比如10万,100万,那么以上四种方式,哪一种效率最高呢,我简单测试了一下,pageSize设为20,list的size分别为10万,和100万,分别跑100次,然后取平均值,如下:

public static void main(String[] args) {    ArrayList
list = new ArrayList
(); for (int i = 0; i < 100000; i++) { list.add(i); } Long time1 = System.currentTimeMillis(); for (int i = 0; i <100 ; i++) { splitList1(list, 20); } Long time2 = System.currentTimeMillis(); for (int i = 0; i <100 ; i++) { splitList2(list, 20); } Long time3 = System.currentTimeMillis(); for (int i = 0; i <100 ; i++) { splitList3(list, 20); } Long time4 = System.currentTimeMillis(); for (int i = 0; i <100 ; i++) { splitList3(list, 20); } Long time5 = System.currentTimeMillis(); System.out.println("list的size为10000,执行100次,平均时间为:"); System.out.println("方法1--->:" + (time2 - time1)/100.0+"ms"); System.out.println("方法2--->:" + (time3 - time2)/100.0+"ms"); System.out.println("方法3--->:" + (time4 - time3)/100.0+"ms"); System.out.println("方法4--->:" + (time5 - time4)/100.0+"ms"); }

  执行结果为:

list的size为100000,执行100次,平均时间为:方法1--->:2.86ms方法2--->:2.08ms方法3--->:0.66ms方法4--->:0.43ms

    从执行结果中可以看到前两种方法效率,明显不如后两种,后两种时间相差不大,但看起来似乎方法4更好一些,再将list的size设为100万时,执行结果为:

list的size为1000000,执行100次,平均时间为:方法1--->:21.65ms方法2--->:14.09ms方法3--->:0.95ms方法4--->:0.57ms

  size设为1000万时,执行结果为:

list的size为1000000,执行100次,平均时间为:方法1--->:138.39ms方法2--->:112.86ms方法3--->:6.63ms方法4--->:6.07ms

  综上所看,方法4的效率稍好于方法3,方法2稍好于方法1,但3和4的效率比1和2要高出一个数量级,主要是因为方法1和2,是逐个设置的,很明显不如subList,在这里推荐方法4,代码简洁,稍微理解下,可读性也不错.


 

 

 

原文链接:https://www.imooc.com/article/41647

来源:慕课网
本文原创发布于慕课网 ,转载请注明出处,谢谢合作

你可能感兴趣的文章
go-mysql,一个易用的mysql接口框架实现
查看>>
POJ3320 Jessica's Reading Problem【尺取法】
查看>>
201671010117 2016-2017-2《Java程序设计》第八周学习Java心得
查看>>
画廊视图(Gallery)的功能和用法
查看>>
自己动手编写一个VS插件(七)
查看>>
Android里面的Toast
查看>>
mysql双机热备的实现
查看>>
前加绩中国、信雅达高级全栈工程师:吴劲松
查看>>
-bash: pod: command not found 解决办法
查看>>
GCD hdu1695容斥原理
查看>>
Node.js:回调函数
查看>>
python 发送邮件 <QQ+腾讯企业邮箱>
查看>>
细数JDK里的设计模式
查看>>
Linux~上部署.net MVC出现的问题与解决
查看>>
DDD~充血模型和失血模型
查看>>
android DPI与分辨率的关系及计算方式
查看>>
forward_list
查看>>
伪分布式网络爬虫框架的设计与自定义实现(一)
查看>>
解决npm ERR! Unexpected end of JSON input while parsing near的方法汇总
查看>>
MySQL 入门
查看>>