使用前提:當列表頁的數據量比較大,而數據源又不是數據庫的時候(如調用第三方接口),無法支持分頁.但是產品那邊爲了頁面統一,用戶體驗,要實現分頁功能的時候.
話不多說,先上代碼:
/**
* 處理列表分頁
* @author zsc
* @param list 分頁的list
* @param pageNum 頁碼
* @param pageSize 每頁條數
* @return java.util.List<T>
* @date 2020/1/19 15:46
**/
private <T extends Serializable> List<T> handlerListPage(List<T> list, int pageNum, int pageSize) {
if (CollectionUtil.isEmpty(list)) {
return new ArrayList<T>();
}
// 每頁大小不能大於總條數
pageSize = Math.min(pageSize, list.size());
// 如果是第一頁 從0開始 到每頁條數+1結束
int fromIndex = 0;
int toIndex = fromIndex + pageSize;
// 不是第一頁
if (1 != pageNum) {
fromIndex = (pageNum - 1) * pageSize;
toIndex = Math.min(fromIndex + pageSize, list.size());
}
if (toIndex > list.size() || fromIndex > toIndex) {
return new ArrayList<T>();
}
return list.subList(fromIndex, toIndex);
}
可以看到上面在處理完分頁參數之後,調用了subList
/**
* Returns a view of the portion of this list between the specified
* <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive. (If
* <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is
* empty.) The returned list is backed by this list, so non-structural
* changes in the returned list are reflected in this list, and vice-versa.
* The returned list supports all of the optional list operations supported
* by this list.<p>
*
* This method eliminates the need for explicit range operations (of
* the sort that commonly exist for arrays). Any operation that expects
* a list can be used as a range operation by passing a subList view
* instead of a whole list. For example, the following idiom
* removes a range of elements from a list:
* <pre>{@code
* list.subList(from, to).clear();
* }</pre>
* Similar idioms may be constructed for <tt>indexOf</tt> and
* <tt>lastIndexOf</tt>, and all of the algorithms in the
* <tt>Collections</tt> class can be applied to a subList.<p>
*
* The semantics of the list returned by this method become undefined if
* the backing list (i.e., this list) is <i>structurally modified</i> in
* any way other than via the returned list. (Structural modifications are
* those that change the size of this list, or otherwise perturb it in such
* a fashion that iterations in progress may yield incorrect results.)
*
* @param fromIndex low endpoint (inclusive) of the subList
* @param toIndex high endpoint (exclusive) of the subList
* @return a view of the specified range within this list
* @throws IndexOutOfBoundsException for an illegal endpoint index value
* (<tt>fromIndex < 0 || toIndex > size ||
* fromIndex > toIndex</tt>)
*/
List<E> subList(int fromIndex, int toIndex);
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
}
private class SubList extends AbstractList<E> implements RandomAccess {
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size;
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
接口內部的文檔描述 Returns a view of the portion of this list between the specified – --返回傳入這個list的指定的一部分視圖. 之後,ArrayList的實現是先校驗了範圍,之後返回了一個SubList對象,給了當前List的默認屬性,入參的範圍.
如果有條件檢索的話,需要先篩選,再分頁像這樣:
/**
* 處理通用返回數據
* @author zsc
* @param list 源list
* @param param 分頁和條件參數
* @return com.zijinph.riskcontrol.dto.CommonTaxPageDTO
* @date 2020/1/21 16:58
**/
private CommonTaxPageDTO processCommonResponse(List<CommonTaxDTO> list, CommonTaxPageParam param) {
CommonTaxPageDTO dto = new CommonTaxPageDTO();
list = filtrationList(list, param.getCondition());
dto.setTotalRecords(CollectionUtil.isEmpty(list) ? 0 : list.size());
dto.setDtoList(handlerListPage(list, param.getPageNum(), param.getPageSize()));
return dto;
}
/**
* 根據表名篩選集合
* @author zsc
* @param list 源list
* @param condition 條件
* @return void
* @date 2020/1/20 18:04
**/
private List<CommonTaxDTO> filtrationList(List<CommonTaxDTO> list, String condition) {
if (!StringUtil.isEmpty(condition)) {
list = list.stream().filter(item -> condition.equals(item.getDeclarationTableName())).collect(Collectors.toList());
}
return list;
}
總結:
如果是類似的業務場景,像博主這邊需要調大數據接口拿數據,可以先解析出List,存入緩存.之後每次僞分頁和條件檢索都從緩存拿,不然每次做分頁都是重新調用接口,解析json,根據規則取值拼接什麼的,太消耗資源.