22

Is there any library that can be used to implement paging for a list?

Let' assume I have a space of 10 lines, and the user can select if he wants to scroll forward or backward by page (thus +- 10 items). This might eg be controlled by -1, 0, +1.

This is probably much work to build a class that prevents scrolling backward/forward if there are not enough items to display, and to self-save the state on which page the user is currently.

So is there anything?

membersound
  • 81,582
  • 193
  • 585
  • 1,120
  • 1
    For web applications: JSF provides paging. – Joop Eggen Oct 30 '13 at 16:18
  • 1
    No not jsf, pure java – membersound Oct 30 '13 at 16:20
  • I was just about to ask what kind of app it is. By "pure Java" do you mean a swing app or a console app? – Joshua Davis Oct 30 '13 at 16:20
  • sorry, I meant console app (this is later to be placed inside an existing architecture, but that does not matter). – membersound Oct 30 '13 at 16:23
  • This kind of structure you need is called a 'zipper'. See http://en.wikipedia.org/wiki/Zipper_%28data_structure%29 , there are java implementations on github. – Pierre Emmanuel Lallemant Oct 30 '13 at 16:28
  • Hm this "zipper" seems to be to be some sort of single-item back and forth. I'm rather looking into pagination... – membersound Oct 30 '13 at 16:30
  • 2
    Unless I'm missing your point, it shouldn't be that difficult. You need to remember the page you're on and the number of items per page. Then you can easily calculate the index of the starting element in the list as either max(0, page * items per page) and the ending element as min(list.size-1, start index + items per page) – Morfic Oct 30 '13 at 16:44
  • 1
    That's right @Grove , you should be able to use list.subList(fromIdx,toIdx) to get a 'view' of the whole list... if that's what you need. No library required. – Joshua Davis Oct 30 '13 at 18:46
  • The problem with using sublist is: Say there are 1000 records in DB for the particular condition. Now, all the records are fetched and then sublist is applied on that list to extract the 10 records from it. Is there any other efficient way than this? – bgth Apr 08 '14 at 20:49

2 Answers2

50

Minor optimization, if you don't really want to create any new list at all.

/**
 * returns a view (not a new list) of the sourceList for the 
 * range based on page and pageSize
 * @param sourceList
 * @param page, page number should start from 1
 * @param pageSize
 * @return
 * custom error can be given instead of returning emptyList
 */
public static <T> List<T> getPage(List<T> sourceList, int page, int pageSize) {
    if(pageSize <= 0 || page <= 0) {
        throw new IllegalArgumentException("invalid page size: " + pageSize);
    }
    
    int fromIndex = (page - 1) * pageSize;
    if(sourceList == null || sourceList.size() <= fromIndex){
        return Collections.emptyList();
    }
    
    // toIndex exclusive
    return sourceList.subList(fromIndex, Math.min(fromIndex + pageSize, sourceList.size()));
}
Community
  • 1
  • 1
kisna
  • 2,869
  • 1
  • 25
  • 30
  • Just stumbled upon this. Why does the page start at 1? If I wanted to have it start at 0 how would the sublist query look like? I've tried and get out of bounds issues. Thanks! – MetaCoder Apr 07 '21 at 14:20
  • @Philban, the page is just a parameter, if yours is 0-index based, then update the validation and simply add +1 to it :), the "javadoc" is the key to avoid issues here – kisna Apr 08 '21 at 01:02
  • Excellent thanks for the response @Kisna. I'm actually going to open a question related to this. Basically i have it working but if lets say the size of the list is 10 and I do page=1&size=10 (everything comes back as expected) BUT if I do page=10&size=10 I also get the entire collection of the list back. Any ideas? – MetaCoder Apr 08 '21 at 10:33
37

I've solved this before. I made a static getPages method that breaks a generic collection into a list of pages (which are also lists). I've provided the code below.

public static <T> List<List<T>> getPages(Collection<T> c, Integer pageSize) {
    if (c == null)
        return Collections.emptyList();
    List<T> list = new ArrayList<T>(c);
    if (pageSize == null || pageSize <= 0 || pageSize > list.size())
        pageSize = list.size();
    int numPages = (int) Math.ceil((double)list.size() / (double)pageSize);
    List<List<T>> pages = new ArrayList<List<T>>(numPages);
    for (int pageNum = 0; pageNum < numPages;)
        pages.add(list.subList(pageNum * pageSize, Math.min(++pageNum * pageSize, list.size())));
    return pages;
}
pscuderi
  • 1,554
  • 12
  • 14