今天碰到一個需求,定時任務,批量從表裏取數據並作一些其餘操做而後再存表,每次取1000條,因爲計算過程比較耗時因此要起多個線程同時跑,須要將List按照指定大小等分,如每100條數據起一個線程,若最後剩餘一份不到100,也放到一個線程裏,網絡上的實現方法有不少,我測試以後理出三種相對比較好的實現方法,以下:java
1 /*第一種方法 思路比較簡單,遍歷list,將元素添加到subList, 2 *每當i到pageSize的時候,將subList添加到listArray並新建,subList 3 */ 4 public static <T> List<List<T>> splitList1(List<T> list, int pageSize) { 5 6 List<List<T>> listArray = new ArrayList<List<T>>(); 7 8 List<T> subList = null; 9 10 for (int i = 0; i < list.size(); i++) { 11 12 if (i % pageSize == 0) { 13 14 subList = new ArrayList<T>(); 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 <T> List<List<T>> splitList2(List<T> list, int pageSize) { List<List<T>> listArray = new ArrayList<List<T>>(); ArrayList<T> subList = new ArrayList<T>(); for (T x : list) { subList.add(x); if (pageSize == subList.size()) { listArray.add(subList); subList = new ArrayList<T>(); } } if (0 != subList.size()) { listArray.add(subList); } return listArray; }
/*第三種方法,用到了java list自帶的方法subList, *先判斷list的size<pageSize的狀況,而後利用subList方法循環切塊 */ public static <T> List<List<T>> splitList3(List<T> list, int pageSize) { List<List<T>> listArray = new ArrayList<List<T>>(); 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 <T> List<List<T>> splitList4(List<T> list, int pageSize) { List<List<T>> listArray = new ArrayList<List<T>>(); 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<Integer> list = new ArrayList<Integer>(); 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"); }
執行結果爲:spa
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萬時,執行結果爲:code
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,代碼簡潔,稍微理解下,可讀性也不錯.blog
原文連接:https://www.imooc.com/article/41647
來源:慕課網
本文原創發佈於慕課網 ,轉載請註明出處,謝謝合做rem