1

I am trying to create a simple pagination routine for values held in an ArrayList. Basically what I want to do is render the first five elements in the ArrayList at first go. And then when users click on Next (increment by another 5) and Previous (decrease by 5).

My logic looks like this:

class foo
{
   private static final int defaultStep = 5;
   private int moveCounter;
   private List<String> values;

   public foo()
   {
     values = new ArrayList<String>();
     values.add("Fiber Channel");
     values.add("Copper Channel");
     ...
   }

  private void pageNext()
  {
   if (moveCounter > -1 && moveCounter < values.size())
   {
    int currentIndex = (moveCounter + 1);
    renderValues(currentIndex, false);
   }
  }

  private void pagePrevious()
  {
   if (moveCounter > -1 && moveCounter <= values.size())
   {
    renderValues(moveCounter-1, true);
   }
  }

 private void renderValues(int startIndex, boolean isPreviousCall)
 {
  if (startIndex > -1)
  {
   StringBuilder html = new StringBuilder();
   List<String> valuesToRender = new ArrayList<String>();
   int checkSteps = 1;
   while (startIndex < values.size())
   {
     valuesToRender.add(values.get(startIndex));
     if (checkSteps == defaultStep) break;
     startIndex++;
     checkSteps++;
   }
   moveCounter = startIndex;

   //TODO: Build html String
   ...
   }
 }
}

I have an issue with pagePrevious call, can you guys help me build the valuesToRender 5-steps up values array before adding the value to render to the valuesToRender array.

I tried doing something like this also:

  for (int start = startIndex, end = values.size() - 1; start < end; start++, end--)
  {
    if (isPreviousCall) valuesToRender.add(values.get(end));
    else valuesToRender.add(values.get(start));

    if (checkSteps == defaultStep) break;
    checkSteps++;
  }

But this doesn't seems to work neither. Can you guys spot and help me fix this issue. Thanks Guys.

Bitmap
  • 12,402
  • 16
  • 64
  • 91

5 Answers5

3

Based on "pscuderi" solution here I've built a wrapping class that can be helpful for someone looking for this:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class PaginatedList<T> {

private static final int DEFAULT_PAGE_SIZE = 10;

private List<T> list;
private List<List<T>> listOfPages;
private int pageSize = DEFAULT_PAGE_SIZE;
private int currentPage = 0;

public PaginatedList(List<T> list) {
    this.list = list;
    initPages();
}

public PaginatedList(List<T> list, int pageSize) {
    this.list = list;
    this.pageSize = pageSize;
    initPages();
}

public List<T> getPage(int pageNumber) {
    if (listOfPages == null || 
        pageNumber > listOfPages.size() ||
        pageNumber < 1) {
        return Collections.emptyList();
    }

    currentPage = pageNumber;
    List<T> page = listOfPages.get(--pageNumber);
    return page;
}

public int numberOfPages() {
    if (listOfPages == null) {
        return 0;
    }

    return listOfPages.size();
}

public List<T> nextPage() {
    List<T> page = getPage(++currentPage);
    return page;
}

public List<T> previousPage() {
    List<T> page = getPage(--currentPage);
    return page;
}

public void initPages() {
    if (list == null || listOfPages != null) {
        return;
    }

    if (pageSize <= 0 || pageSize > list.size()) {
        pageSize = list.size();
    }

    int numOfPages = (int) Math.ceil((double) list.size() / (double) pageSize);
    listOfPages = new ArrayList<List<T>>(numOfPages);
    for (int pageNum = 0; pageNum < numOfPages;) {
        int from = pageNum * pageSize;
        int to = Math.min(++pageNum * pageSize, list.size());
        listOfPages.add(list.subList(from, to));
    }
}

public static void main(String[] args) {
    List<Integer> list = new ArrayList<Integer>();
    for (int i = 1; i <= 62; i++) {
        list.add(i);
    }

    PaginatedList<Integer> paginatedList = new PaginatedList<Integer>(list);
    while (true) {
        List<Integer> page = paginatedList.nextPage();
        if (page == null || page.isEmpty()) {
            break;
        }

        for (Integer value : page) {
            System.out.println(value);
        }

        System.out.println("------------");
    }
}

}
Community
  • 1
  • 1
Qussay Najjar
  • 561
  • 3
  • 7
1

Change

if (moveCounter > -1 && moveCounter <= archive.size())
{
  renderValues(moveCounter-1, true);
}

to

if (moveCounter > 0 && moveCounter <= archive.size())
{
  renderValues(moveCounter-1, true);
}
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
0

I would do it like this:

I'm not sure what renderValues does, and whether we have to substract 1 or maybe defaultStep from the upper bound of the moveCounter.

private void pageMove (int step)
{
    moveCounter = moveCounter + step;
    if (moveCounter < 0) moveCounter = 0;
    if (moveCounter > values.size ()) moveCounter = values.size ();
    renderValues (currentIndex, false);
}

private void pageNext ()
{
    pageMove (defaultStep);
}

private void pagePrevious ()
{
    pageMove (-defaultStep);
}

The first 3 lines could be packed into two big ternary experssions like so:

mc = ((mc + s) < 0) ? 0 : ((mc + s) > vs) ? vs : (mc + s); 

but the 3 lines solution is better to follow.

user unknown
  • 35,537
  • 11
  • 75
  • 121
  • Doing it this way, would `renderValues(..)` stay as it is or you think the second option stands fit - or perhaps needs changing?! – Bitmap Apr 25 '12 at 11:32
  • Well, I don't understand what 'renderValues' is doing. The variable names are quiete confusing. StartIndex and checkSteps are mutable? Maybe you better name them i or n. I thought the job of pagePrev is to set the scope somehow back - from 17-22 to 12-17 for example, and to check for boundary violation (prevent -3). The later work of layout is done in renderValues. Make short methods which have only one task to solve. – user unknown Apr 25 '12 at 12:16
0

Here is a simple java function for pagination. Note that the page starts from 0 (first page)

public List<Object> pagedResponse(List<Object> allItems, int page, int limit){
    int totalItems = allItems.size();
    int fromIndex = page*limit;
    int toIndex = fromIndex+limit;
    if(fromIndex <= totalItems) {
        if(toIndex > totalItems){
            toIndex = totalItems;
        }
        return allItems.subList(fromIndex, toIndex);
    }else {
        return Collections.emptyList();
    }
}
NitishDeshpande
  • 435
  • 2
  • 6
  • 19
0
List<List<T>> partition = Lists.partition(list, pageSize);

Use the index as the page number to fetch page.

MayurB
  • 3,609
  • 2
  • 21
  • 36