java web分頁思想很常用,本質思想是:由於數據量太大,一頁顯示不完的,所以需要分頁顯示。那麼分頁核心就是如何計算每一頁的起始下標。
分頁思想總結起來就是分批次處理,除了用在web頁面的分頁,還適用於數據庫入庫和多線程操作等應用場景。
只要掌握了其原理,便可舉一反三。
解析開始:
1.總共有 len 條數據,但每次只能處理 batchSize 條記錄,所以需要分爲 times 次來處理。
a.如果能整除比較簡單:
times = len / batchSize
b.如果不能整除,只需要把餘數單獨作爲一輪來處理就行了:
if(len%batchSize != 0) //如果不能整除,則要多跑一輪
times++;
/////////////////////////////哈哈分割線/////////////////////////////////////////////
2.當把批次確定好了之後,接下來計算每一輪的起始和結束下標即可。
//以len=32,batchSize=10,times=(32/10)+1=4 爲例
(PS粗心的同學:整型數據相除捨去小數位,只取整數據位)
那麼第一輪:[0 --9]
第二輪:[10 -- 19] //個位數是不是很規律:-)
第三輪:[20 --29]
第四輪:[30 -- 31]
或者:
第一輪:[1 -- 10]
第二輪:[11 --20] //個位數是不是很規律:-)
第三輪:[21 --30]
第四輪:[31 -- 32]
/////////////////////////////哈哈分割線/////////////////////////////////////////////
so,下面上代碼:
a.下標從0開始計算的情況
for(int i=1; i<=times; i++)
{
start= (i-1)*batchSize; //=0, 10, 20, 30
end= start + batchSize; //=10 ,20, 30, 32
if(end>=len) //最後一輪數據未滿,所以end 要特殊處理
end= len;
//這個是開區間[start,end),這個區間內的數據就是本輪要處理的數據
do something(start,end)//傳入區間參數,調用函數完成計算
}
b.下標從1開始計算的情況
for(int i=1; i<=times; i++)
{
start= (i-1)*batchSize+1; //=1 ,11, 21,31
end= start + batchSize-1; //=10, 20,30,32
if(end>=len) //最後一輪數據未滿,所以end 要特殊處理
end= len;
//這個是閉區間[start,end],這個區間內的數據就是本輪要處理的數據
do something(start,end)//傳入區間參數,調用函數完成計算
}
下面貼上源代碼:
a.下標從0開始計算的情況
/**
* 利用分頁思想, 分批次入庫
* @Title: batchWriteDB
* @param list list表數據過大,需要分批入庫
* @param batchSize 每輪入庫數據量
* @param sp spark api
* @param tbName 表名
* @param beanClass 表的bean對象
*/
public static <T> void batchWriteDB(List<T> list,int batchSize,SparkApi sp, String tbName, Class<T> beanClass)
{
int len = list.size();//總數
int times = len/batchSize;//輪數
if(len%batchSize != 0)//如果不能整除,則要多跑一輪
times++;
Log.log("-----總共"+len+" 條記錄總需要分爲"+times+" 輪來入庫,每輪寫入"+batchSize+" 條記錄");
int start = 1;
int end = 1;
for(int i=1;i<=times; i++)
{
start = (i-1)*batchSize;
end = start + batchSize;
if(end>=len)//最後一輪數據未滿
end = len;
//子集爲開區間[0,len) =[0, len-1]
List<T> list2 = list.subList(start,end);
Log.log("第"+i+"輪入庫:list2.size()= "+list2.size()+", list.size()="+list.size());
Log.log("start="+start+", end="+end+" length="+(end-start));
Dataset<Row> squaresDF = sp.createDataFrame(list2, beanClass);
squaresDF.coalesce(Config.nSparkCores).write().partitionBy("timeh").mode(SaveMode.Append).saveAsTable(tbName);
squaresDF = null;
}
}
b.下標從1開始計算的情況
public static void hbaseMultiInsert(int dataNum,int ThreadNum) throws InterruptedException
{
if(dataNum%ThreadNum!=0)//如果不能整除,則要多跑一輪
ThreadNum ++;
int pageSize = dataNum/ThreadNum;//分頁思想:每輪執行多少數據
int start = 1;
int end = 1;
//同步器
final CountDownLatch cdl = new CountDownLatch(ThreadNum);
long starttime=System.currentTimeMillis();
for(int k=1;k<=ThreadNum;k++)
{
start = (k-1)*pageSize+1;
end = start+pageSize-1;
if(end>=dataNum)//最後一輪數據未滿
end = dataNum;
//extends Thread這樣調用
new MyThread(cdl,start,end).start();
/*
//MyThread implements Runnable這樣調用
MyThread my = new MyThread(start,end);
Thread thread = new Thread(my);
thread.start();
*/
}
try {
cdl.await();
long spendtime=System.currentTimeMillis()-starttime;
System.out.println( ThreadNum+"個線程花費時間:"+spendtime/1000.0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}//hbaseMultiInsert