批量分页

2023-12-31

java

再也无需前思后想,一切岂非已然过往。——《且听风吟》

今天分享一个装一个分批分页,传入页码、分页条数,然后查询分页条数+1条数据,这里的+1是为了判断还有下一页数据,然后查询到后,再按照传入的lambda条件筛选,筛选完后的数据添加进集合,添加到集合后如果满足当前分页所需条数,就返回数据

这里需要做一个容错,当时间超过后直接返回,避免传入的lambda predicate一直为false导致死循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.experimental.UtilityClass;
import org.dromara.streamquery.stream.core.stream.Steam;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;

@UtilityClass
public final class PageUtil {

public static <T> Page<T> batchFlow(Page<T> page, BiFunction<Long, Long, List<T>> queryFunc,
Function<List<T>, Predicate<T>> predFun, int timeout) {
var pageNum = page.getCurrent();
var pageSize = page.getSize();
List<T> results = new ArrayList<>();
Predicate<T> predicate = predFun.apply(results);
page.setRecords(results);
var startTime = System.currentTimeMillis();
while (results.size() < pageSize && (timeout < 0 || (System.currentTimeMillis() - startTime) < timeout)) {
var items = queryFunc.apply(pageNum, pageSize + 1);
boolean noNextPage = items.size() < pageSize + 1;
var filteredItems = Steam.of(items).filter(predicate).toList();
page.setTotal(noNextPage ? (page.getCurrent() - 1) * page.getSize() + filteredItems.size() :
page.getCurrent() * page.getSize() + 1);
for (T item : filteredItems) {
if (results.size() < pageSize) {
results.add(item);
} else {
// Enough items for this page, extra items indicate there's a next page
return page;
}
}
if (noNextPage) {
return page;
}
// Next page
pageNum++;
}
return page;
}

}

测试用例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.dromara.streamquery.stream.core.collection.Lists;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.stream.Stream;

/**
* PageUtilTest
*
* @author VampireAchao<achao @ hutool.cn>
*/
class PageUtilTest {

@Test
void batchPagingTest() {
Page<Object> page = PageUtil.batchFlow(new Page<>(1, 10),
(current, size) -> {
return new ArrayList<>();
}, list -> i -> false, 100);
Assertions.assertTrue(page.getRecords().isEmpty());

Page<Long> page1 = PageUtil.batchFlow(new Page<>(1, 10), (current, size) -> {
return Stream.iterate((current - 1) * size + 1, i -> i <= current * size, i -> ++i).toList();
}, list -> i -> i % 2 == 0, -1);
Assertions.assertEquals(Lists.of(2L, 4L, 6L, 8L, 10L, 12L, 14L, 16L, 18L, 20L), page1.getRecords());

Page<Long> page2 = PageUtil.batchFlow(new Page<>(2, 10), (current, size) -> {
return Stream.iterate(1L, i -> ++i).limit(9).toList();
}, list -> i -> true, -1);
Assertions.assertEquals(19, page2.getTotal());
Assertions.assertEquals(Lists.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L), page2.getRecords());

}

}