Как разбить список на страницы
Короткий ответ
Страница — это часть списка от (page - 1) * size длиной size. Через поток её удобно получить с skip() и limit():
void main() {
var items = IntStream.rangeClosed(1, 23).boxed().toList();
int page = 3;
int size = 10;
var current = items.stream().skip((long) (page - 1) * size).limit(size).toList();
IO.println(current);
}Результат:
[21, 22, 23]Количество страниц
Число страниц — деление с округлением вверх:
void main() {
int total = 23;
int size = 10;
IO.println(Math.ceilDiv(total, size));
}Результат:
3Через subList
subList() не создаёт поток и работает быстрее, но границы нужно ограничить вручную:
<T> List<T> page(List<T> items, int page, int size) {
int from = Math.min((page - 1) * size, items.size());
int to = Math.min(from + size, items.size());
return items.subList(from, to);
}
void main() {
var names = List.of("Anna", "Oleg", "Boris", "Ivan", "Maria");
IO.println(page(names, 2, 2));
IO.println(page(names, 5, 2));
}Результат:
[Boris, Ivan]
[]Частая ошибка
Не ограничить конец страницы размером списка. Последняя неполная страница выходит за границы:
void main() {
var names = List.of("Anna", "Oleg", "Boris");
IO.println(names.subList(2, 4));
}Результат:
Exception in thread "main" java.lang.IndexOutOfBoundsException: toIndex = 4Функции из этого ответа
- List.subList() — Возвращает часть списка между двумя индексами.
- Stream.skip() — Пропускает первые N элементов потока.
- Stream.limit() — Обрезает поток до первых N элементов.
- Math.ceil() — Округляет вверх — до ближайшего большего или равного целого.