Skip to content

Instantly share code, notes, and snippets.

@megabites2013
Forked from josericardo/PageableCollection.java
Created February 18, 2020 11:15
Show Gist options
  • Save megabites2013/b8d52ee4f899768881b135c06fef5ea9 to your computer and use it in GitHub Desktop.
Save megabites2013/b8d52ee4f899768881b135c06fef5ea9 to your computer and use it in GitHub Desktop.
Helper to iterate over pageable sources. Should reduce memory usage when querying large tables via Spring Data.
======================================
Usage:
Fetcher<Source, MyEntity> f = new Fetcher<Source, MyEntity>(source) {
@Override
public List<MyEntity> fetch(Pageable pageRequest)
{
return source.findAll(pageRequest);
}
};
PageableCollection<Source,MyEntity> pageableCollection = new PageableCollection<Source, MyEntity>(f);
for (MyEntity e : pageableCollection) {
// ...
}
============================================================================
public class PageableCollection<T> implements Iterable<T>
{
private static final int DEFAULT_PAGE_SIZE = 100;
private Fetcher<?, T> fetcher;
private int pageSize;
public PageableCollection(Fetcher<?, T> f) {
this(f, DEFAULT_PAGE_SIZE);
}
public PageableCollection(Fetcher<?, T> f, int pageSize)
{
this.fetcher = f;
this.pageSize = pageSize;
}
@Override
public Iterator<T> iterator()
{
return new PageableIterator<T>(fetcher, pageSize);
}
}
/**
* Initially makes sense only inside the PageableCollection class
*/
class PageableIterator<T> implements Iterator<T>
{
private static final int FIRST_PAGE = 0;
private List<T> currentData;
private int cursor;
private int pageSize;
private Pageable page;
private Fetcher<?, T> fetcher;
public PageableIterator(Fetcher<?, T> f, int pageSize) {
this.fetcher = f;
this.pageSize = pageSize;
page = new PageRequest(FIRST_PAGE, pageSize);
currentData = new ArrayList<T>();
}
@Override
public boolean hasNext()
{
if (hasDataLoaded()) {
return true;
}
tryToFetchMoreData();
return !currentData.isEmpty();
}
private void tryToFetchMoreData()
{
currentData = fetcher.fetch(page);
page = new PageRequest(page.getPageNumber()+1, pageSize);
cursor = 0;
}
private boolean hasDataLoaded()
{
return cursor < currentData.size();
}
@Override
public T next()
{
return currentData.get(cursor++);
}
@Override
public void remove()
{
throw new UnsupportedOperationException();
}
}
public abstract class Fetcher<S, T>
{
protected S source;
public Fetcher(S s) {
this.source = s;
}
public abstract List<T> fetch(Pageable pageRequest);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment