使用前提:当列表页的数据量比较大,而数据源又不是数据库的时候(如调用第三方接口),无法支持分页.但是产品那边为了页面统一,用户体验,要实现分页功能的时候.
话不多说,先上代码:
/**
* 处理列表分页
* @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,根据规则取值拼接什么的,太消耗资源.