javacollectionspaginationiterationguava

How to return N consecutive elements from a Collection?


I am passed a collection of objects (some Contact class in my case) and need to return a page from that collection. My code feels much longer than it needs to be. Am I missing some libraries that could perform that more elegantly than iterating over each element one at a time like I do below?

protected Collection<Contact> getPageOfContacts(
  Collection<Contact> contacts, int pageIndex, int pageSize) {
  if (pageIndex < 0 || pageSize <= 0
    || pageSize > contacts.size()) {
    return contacts;
  }
  int firstElement = pageIndex * pageSize;
  int lastElement = (pageIndex + 1) * pageSize - 1;
  Collection<Contact> pagedContacts = new ArrayList<Contact>();
  int index = -1;
  for (Contact contact : contacts) {
    index++;
    if (index < firstElement) {
      continue;
    }
    if (index > lastElement) {
      break;
    }
    pagedContacts.add(contact);
  }
  return pagedContacts;
}

Solution

  • You could use Guava Iterables.partition:

    protected <T> Collection<T> getPageOfContacts(
            Collection<T> contacts, int pageIndex, int pageSize) {
        return Lists.newArrayList(
            Iterables.partition(contacts, pageSize)).get(pageIndex);
    }
    

    A more complex version does not create all pages to pick the right one, but stops when the right page is found.

    protected <T> Collection<T> getPageOfContacts(
            Collection<T> contacts, int pageIndex, int pageSize) {
        Iterator<List<T>> partitions = Iterators.partition(contacts.iterator(), pageSize);
    
        for(int page = 0; page<pageSize && partitions.hasNext(); page++){
            List<T> partition = partitions.next();
            if(page == pageIndex) return partition;
        }
        return Collections. <T> emptyList(); //or fail
    }
    

    Update:

    Thanks to ColinD to point out that:

    Iterables.get(Iterables.partition(contacts, pageSize), pageIndex)
    

    is a simpler implementation.