Bitmap
Bitmap

Reputation: 12538

Paginating an ArrayList

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.

Upvotes: 1

Views: 13558

Answers (5)

MayurB
MayurB

Reputation: 3649

List<List<T>> partition = Lists.partition(list, pageSize);

Use the index as the page number to fetch page.

Upvotes: 0

NitishDeshpande
NitishDeshpande

Reputation: 495

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();
    }
}

Upvotes: 1

Qussay Najjar
Qussay Najjar

Reputation: 591

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("------------");
    }
}

}

Upvotes: 4

user unknown
user unknown

Reputation: 36229

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.

Upvotes: 0

Marko Topolnik
Marko Topolnik

Reputation: 200158

Change

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

to

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

Upvotes: 1

Related Questions