Skip to Content

How to implement pagination in Java?

Pagination is a common technique used in applications to divide content into discrete pages. This improves performance and usability by only loading a subset of data at a time. In this article, we will learn how to implement pagination in a Java application.

Why Use Pagination?

There are several benefits to using pagination in an application:

  • Improves performance – Only a subset of data is loaded and rendered at a time. This reduces memory usage and speeds up response times.
  • Enhances usability – Long lists are broken up into smaller chunks that are easier to scan and navigate.
  • Facilitates sorting/filtering – Applying these actions to smaller subsets of data is faster.
  • Allows progressive loading – Data can be loaded asynchronously as the user navigates between pages.

Without pagination, performance and usability would suffer as the dataset grows larger. Pagination should be considered in any application displaying long lists of data like search results, products in a catalog, etc.

Pagination Components

Implementing pagination requires a few key components:

  • Data source – The full set of data to be paginated
  • Page size – The number of items displayed per page
  • Current page – The specific page being viewed
  • Total pages – Derived from total items/page size
  • Navigation – UI controls to view other pages (page numbers, next/previous buttons, etc)

With these core components defined, we can query a subset of data for each page and build navigation that allows browsing between pages.

Pagination Approaches

There are a couple common approaches for implementing pagination in Java:

1. Offset/Limit

This uses offset and limit parameters in the query to retrieve a page of data:

  • Offset – Index of first item desired
  • Limit – Number of items per page (page size)

For example, to retrieve items 11-20 for display on page 2 with page size 10:

“`java
List items = query(“SELECT * FROM items LIMIT 10 OFFSET 10”);
“`

The offset would increment by the page size for each page.

2. Keyset Pagination

This uses a unique identifier (or set of columns) to paginate data:

  • First page query has no bounds
  • Subsequent pages bounded by last item’s key from prior page

For example:

“`java
// First page
List firstPage = query(“SELECT * FROM items”);

// Second page
String lastItemKey = firstPage.get(firstPage.size() – 1).getKey();
List secondPage = query(“SELECT * FROM items WHERE key > ?”, lastItemKey);
“`

This requires a unique, immutable key but doesn’t depend on offset rows, so it avoids issues like skipped/duplicated items when data changes.

Implementing Offset/Limit Pagination

Let’s walk through an example implementing basic offset/limit pagination in a Java application.

1. Define page size

First, define the number of items to display per page. This will remain constant.

“`java
// Page size
int pageSize = 10;
“`

2. Calculate total pages

Based on the page size and total number of items, we can determine the total number of pages needed.

“`java
// Total items
int totalItems = dao.count();

// Calculate total pages
int totalPages = totalItems / pageSize;

if(totalItems % pageSize > 0) {
totalPages++;
}
“`

3. Store current page

Track the current page number being viewed. This will start at 1 and increment/decrement as the user navigates.

“`java
// Current page
int currentPage = 1;
“`

4. Calculate offset

On each page request, calculate the offset based on page size and current page number.

“`java
// Calculate offset
int offset = (currentPage – 1) * pageSize;
“`

5. Query for page data

Use the offset and page size to query for a subset of items to display.

“`java
List items = dao.query(offset, pageSize);
“`

6. Build page navigation

Build UI to view other pages, like page numbers or next/previous buttons.

“`java
// Page numbers
for(int i = 1; i <= totalPages; i++) { pages.add(i); } // Next/Previous if(currentPage < totalPages) { nextEnabled = true; } if(currentPage > 1) {
prevEnabled = true;
}
“`

Update current page when navigation used and re-query data.

7. Render page

Display the page of items and navigation UI to the user!

Keyset Pagination Example

Here is an example of keyset pagination using a database table with an auto-increment ID column as the unique key.

1. Query first page

“`java
// Get first page
List firstPage = dao.query(“SELECT * FROM items”);
“`

2. Get last item’s key

“`java
// Key of last item
int lastKey = firstPage.get(firstPage.size() – 1).getId();
“`

3. Query next page

“`java
// Get next page
List nextPage =
dao.query(“SELECT * FROM items WHERE id > ?”, lastKey);
“`

4. Repeat with new last key

To paginate further, repeat the process using the new last item’s key from each page.

Additional Pagination Tips

Some other tips for implementing pagination:

  • Display page numbers close to current page prominently, eg 1 2 [3] 4 5.
  • Indicate when more pages are available that can be navigated to.
  • If dataset is small enough, display all data on one page.
  • Remember page state between requests if navigating away and back.
  • Cache queries if using an expensive data source like a database.
  • Return total item count alongside paged data for calculating pages.

Conclusion

Pagination is essential for providing a scalable browsing experience. In Java, it can be implemented via offset/limit queries or keyset pagination. Key considerations are page size, total pages, navigation, and caching. Following pagination best practices will lead to happy users and performant applications.