在處理一個分頁工做時,須要作一個向上取整的操做,相似這樣:java
// 總數
int totalSize = 799;
// 頁大小
int pageSize = 200;
// 計算頁數須要向上取整
// 這裏的向上取整如何處理?
int pageCount = (double)totalSize / pageSize;
複製代碼
這個向上取整計算其實很經常使用,可是彷佛沒有一個比較標準的處理方式。工具
方案一:檢查餘數spa
檢查餘數是否爲0,這是我經常使用的寫法。.net
// ...
int pageCount = totalSize / pageSize;
if (totalSize % pageSize > 0) {
pageCount++;
}
複製代碼
這種方式很笨,同時還有點囉嗦。code
**方案二(不推薦!):Math.ceil(double x) **cdn
也許看完第一個方案已經有人在說了,官方Math工具就提供了向上取整的方法,爲何不用呢?blog
// ...
int pageCount = (int)Math.ceil((double)totalSize / pageSize);
複製代碼
最大的問題:Math.ceil的返回類型是double。get
且不說這個場景是兩個整型運算,結果也是整型,中間就要通過兩次類型轉換操做,看起來不夠流暢;咱們還應該考慮到在類型轉換中可能存在的精度丟失問題。博客
精度丟失可能僅僅在很極端的場景下出現,可一旦出現就是很是難以排查的隱式bug。舉個例子:it
再舉個例子,假設使用double類型的pageCount,以下一段代碼就有可能出現ArrayOutOfBoundsException:
// ...
double pageCount = 2d; // 可能實際存儲的是2.000000000000001,請意會
for (int page = 0; page < pageCount; page++) {
// Array或List的遍歷操做
}
複製代碼
在任何可能出現與浮點型數據進行比較,或浮點型與整型的類型轉換都必須很是注意。
方案三(推薦):增長一點小處理
int pageCount = (totalSize + pageSize - 1) / pageSize;
複製代碼
這個計算方式在一行代碼內解決,沒有類型轉換或精度丟失,處理上是進位思想,只要理解了就很是天然。
惟一的缺點是若是值過大可能產生溢出,但足夠知足絕大多數場景。
爲何Math.ceil返回的是浮點數?
是的,返回浮點整數雖然符合ceil的語義,但並不符合咱們日常的直觀理解,若是能返回整型數該多好?
可是這個方法的入參就是double類型,而不管是int類型或是long類型的表示範圍都遠遠小於double類型的範圍,若是使用整型就有可能表示不了,於是形成這一奇怪的現實。
表示範圍詳見參考資料。
便捷的List切分方式
寫到一半時想了想,實際上我本次的處理場景是將一個總體任務的List數據水平切分爲多個子任務List,再進行分發處理。
若是是針對List的切分場景,其實很是推薦使用Google的guava包來處理:
// 直接分割,很是方便
List<List<Object>> subTaskLists = Lists.partition(taskList, pageSize);
複製代碼
Lists.partition的實現方式:固定步長,屢次取subList。
使用Math.ceil將Java四捨五入爲int - 問答 - 雲+社區 - 騰訊雲
java中short、int、long、float、double取值範圍 - qfikh的博客 - CSDN博客
本文搬自個人博客,歡迎參觀!