The process of pagination is to divide a big dataset into smaller, more manageable pieces, or pages. Most of the time, each page has a limited number of things or records on it. Users can move from page to page to find the information they want, which makes data retrieval and display more efficient.
There are various pagination techniques, but two commonly used approaches are:
Offset-based pagination
Keyset pagination
Offset-based pagination relies on providing the page number and the number of items per page (page size). By using the offset and limit values, the database query retrieves a specific part of the data. This technique is suitable for datasets that don't change frequently.
Here is a simple example of offset-based pagination in Java Swing.
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Main extends JFrame { private static final int PAGE_SIZE = 5; private static final String[] ITEMS = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12", "Item 13", "Item 14", "Item 15", "Item 16", "Item 17", "Item 18", "Item 19", "Item 20", "Item 21", "Item 22", "Item 23" }; private JPanel mainPanel; private JLabel currentPageLabel; private JButton previousButton; private JButton nextButton; private JTextArea itemsTextArea; private int currentPage = 1; public Main() { setTitle("Pagination Example"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setPreferredSize(new Dimension(300, 200)); mainPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10)); currentPageLabel = new JLabel(); previousButton = new JButton("Previous"); nextButton = new JButton("Next"); itemsTextArea = new JTextArea(10, 20); previousButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (currentPage > 1) { currentPage--; updatePage(); } } }); nextButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int totalPages = (int) Math.ceil((double) ITEMS.length / PAGE_SIZE); if (currentPage < totalPages) { currentPage++; updatePage(); } } }); mainPanel.add(previousButton); mainPanel.add(currentPageLabel); mainPanel.add(nextButton); mainPanel.add(new JScrollPane(itemsTextArea)); add(mainPanel); pack(); setLocationRelativeTo(null); updatePage(); } private void updatePage() { currentPageLabel.setText("Page " + currentPage); // Calculate the starting and ending indexes for the current page int startIndex = (currentPage - 1) * PAGE_SIZE; int endIndex = Math.min(startIndex + PAGE_SIZE, ITEMS.length); // Clear the previous items and add the new ones itemsTextArea.setText(""); for (int i = startIndex; i < endIndex; i++) { itemsTextArea.append(ITEMS[i] + "\n"); } // Update the GUI revalidate(); repaint(); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new Main().setVisible(true); } }); } }
Line 21: The currentPage
variable represents the current page number and is initially set to 1.
Lines 23–65: The constructor of the Main
class. It sets up the GUI components, adds event listeners to the buttons, and initializes the window.
Lines 24–26: The window title, default close operation, and preferred size of the window are set.
Line 28: The mainPanel
is created with a FlowLayout
manager, which arranges the components in a single row with a specified gap.
Lines 29–32: The currentPageLabel
, previousButton
, nextButton
, and itemsTextArea
components are initialized.
Lines 34–53: Action listeners are added to the previous and next buttons using anonymous inner classes. These listeners handle the button clicks and update the current page accordingly.
Lines 62–64: The frame is packed, centered on the screen, and the updatePage
method is called to display the initial page.
Lines 67–83: The updatePage
method updates the GUI based on the current page. It sets the current page label, calculates the starting and ending indexes for the page, clears the previous items, and adds new items to the text area. Finally, it updates the GUI by calling revalidate
and repaint
.
Keyset pagination uses the values of a unique key (like an ID or timestamp) to figure out which pages come next and which ones come before. It gets rid of the need for offsets and improves speed when working with big datasets or with data that changes often.
Here is a simple example of keyset-based pagination in Java Swing.
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.*; public class Main extends JFrame { private TreeSet<String> data; private JLabel pageLabel; private JButton prevButton; private JButton nextButton; private JTextArea outputTextArea; private static final int PAGE_SIZE = 10; private NavigableSet<String> currentPage; private ListIterator<String> currentPageIterator; public Main() { // Initialize your data set (sorted TreeSet in this example) data = new TreeSet<>(); data.add("Apple"); data.add("Banana"); data.add("Cherry"); data.add("Durian"); data.add("Grapes"); data.add("Kiwi"); data.add("Mango"); data.add("Orange"); data.add("Peach"); data.add("Pear"); data.add("Apple2"); data.add("Banana2"); data.add("Cherry2"); data.add("Durian2"); data.add("Grapes2"); data.add("Kiwi2"); // Set up the UI setTitle("Keyset Pagination Example"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout()); JPanel paginationPanel = new JPanel(); prevButton = new JButton("Previous"); nextButton = new JButton("Next"); pageLabel = new JLabel("Page: 1"); outputTextArea = new JTextArea(); JScrollPane scrollPane = new JScrollPane(outputTextArea); add(scrollPane, BorderLayout.CENTER); paginationPanel.add(prevButton); paginationPanel.add(pageLabel); paginationPanel.add(nextButton); add(paginationPanel, BorderLayout.SOUTH); prevButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { showPreviousPage(); } }); nextButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { showNextPage(); } }); // Display the initial page showPage(1); pack(); setLocationRelativeTo(null); setVisible(true); } private void showPage(int page) { int startIndex = (page - 1) * PAGE_SIZE; currentPage = data.stream() .skip(startIndex) .limit(PAGE_SIZE) .collect(TreeSet::new, TreeSet::add, TreeSet::addAll); currentPageIterator = new ArrayList<>(currentPage).listIterator(); updateUI(page); } private void showNextPage() { if (currentPageIterator.hasNext()) { currentPageIterator.next(); } if (!currentPageIterator.hasNext()) { int currentPageNumber = Integer.parseInt(pageLabel.getText().substring(6)); showPage(currentPageNumber + 1); } else { updateUI(Integer.parseInt(pageLabel.getText().substring(6))); } } private void showPreviousPage() { if (currentPageIterator.hasPrevious()) { currentPageIterator.previous(); } if (!currentPageIterator.hasPrevious()) { int currentPageNumber = Integer.parseInt(pageLabel.getText().substring(6)); showPage(currentPageNumber - 1); } else { updateUI(Integer.parseInt(pageLabel.getText().substring(6))); } } private void updateUI(int page) { pageLabel.setText("Page: " + page); // Update your UI with the current page's data outputTextArea.setText("Items on Page " + page + ":\n"); while (currentPageIterator.hasNext()) { outputTextArea.append(currentPageIterator.next() + "\n"); } outputTextArea.append("------------------------------------\n"); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new Main(); } }); } }
Lines 8–18: The class members are defined, including a TreeSet
called data
to store the data set, and GUI components such as JLabel
, JButton
, and JTextArea
for displaying the pagination UI and output.
Lines 20–38: The constructor for the Main
class is defined. Inside the constructor, the data set is initialized with sample data.
Lines 60–72: Action listeners are added to the "Previous" and "Next" buttons to handle the corresponding button clicks.
Lines 75: The showPage
method is called to display the initial page.
Lines 82–91: The showPage
method is defined. It takes a page number as input and calculates the start index for the current page. It then creates a TreeSet
called currentPage
by skipping the appropriate number of elements and limiting the size to PAGE_SIZE
. The currentPageIterator
is also initialized to iterate over the current page's data.
Lines 93–103: The showNextPage
method is called when the "Next" button is clicked. It checks if there is a next element in the currentPageIterator
and moves the iterator to the next element if available. If there is no next element, it determines the current page number, increments it by 1, and calls the showPage
method to display the next page. If there is a next element, it updates the UI without changing the page number.
Lines 105–115: The showPreviousPage
method is similar to showNextPage
but handles the "Previous" button click. It checks if there is a previous element in the currentPageIterator
and moves the iterator to the previous element if available. If there is no previous element, it determines the current page number, decrements it by 1, and calls the showPage
method to display the previous page. If there is a previous element, it updates the UI without changing the page number.
Lines 117–126: The updateUI
method updates the UI with the current page number and the data for the current page. It sets the page label text, clears the output text area, and appends the current page's data to the text area.
Implementing pagination in Java is crucial for efficient data handling and enhanced user experience. By using offset-based or keyset pagination techniques, you can break down large datasets into manageable pages.
Free Resources