How to return N consecutive elements from a collection?

I was given a set of objects (some Contact class in my case) and you need to return a page from this collection. My code is much longer than necessary. I am missing some libraries that could perform more elegantly than repeating each element at a time, as 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; } 
+6
java collections iteration guava paging
source share
6 answers

You can 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); } 

The more complex version does not create all pages to select the correct one, but stops when the right page is detected.

 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 for indicating that:

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

- simpler implementation.

+11
source share

If you can require the data to be unloaded to be a List , you can get a subview of a single page using Guava :

 public <T> List<T> getPage(List<T> list, int pageIndex, int pageSize) { return Lists.partition(list, pageSize).get(pageIndex); } 

It does not require copying or iteration (it uses sublist views of the source list) and processes the final page, which has less than pageSize elements transparently.

For an arbitrary Iterable or Collection I would do the following:

 public <T> List<T> getPage(Iterable<T> iterable, int pageIndex, int pageSize) { return Iterables.get(Iterables.partition(iterable, pageSize), pageIndex); } 

By providing both of these methods, you can efficiently process objects that are known to be lists at compile time, and any other type of Iterable , as efficient as possible.

+6
source share

If you need a specific order for your elements, you should use List , not collection . The main difference between List and collection is that List has a fixed order for items. It also defines a very convenient subList(int start, int end) method that creates a sub-list, which is an alias of the original list containing only those items that you want, without the overhead of copying them to a new list.

+4
source share

The List interface provides a subList method that accepts a start index and an end index. See http://download.oracle.com/javase/6/docs/api/java/util/List.html#subList(int,%20int ). The returned sublist is supported by the original list, so you probably want to do something like

 protected Collection<Contact> getPageOfContacts(...) { return new ArrayList<Contact>(original.subList(start,end)); } 
+1
source share
 return new ArrayList<Contact>(new ArrayList<Contact>(contacts).subList(firstElement, lastElement)); 

Note: this will return the subscript exclusive lastElement

Note 2: the result is copied to another list for the reasons mentioned by Kevin.

0
source share
 Iterables.partition(contacts, pageSize).forEachRemaining(paginatedContacts->{/*Operation here*/}); 
0
source share

All Articles