Skip to content

Instantly share code, notes, and snippets.

@alexmoore
Created December 9, 2015 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexmoore/d1dea3079847a3ac45df to your computer and use it in GitHub Desktop.
Save alexmoore/d1dea3079847a3ac45df to your computer and use it in GitHub Desktop.
package Blah;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class SelectManyIterable<TSource, TResult> implements Iterable<TResult>
{
public interface TransformProvider<TSource, TResult>
{
Iterator<TResult> selectInnerIterator(TSource sourceObject);
}
private final Iterable<TSource> source;
private final TransformProvider<TSource, TResult> transformProvider;
public SelectManyIterable(Iterable<TSource> source, TransformProvider<TSource, TResult> selector)
{
this.source = source;
this.transformProvider = selector;
}
@Override
public Iterator<TResult> iterator()
{
return new SelectManyIterator<TSource, TResult>(source.iterator(), transformProvider);
}
private static class SelectManyIterator<TSource, TResult> implements Iterator<TResult>
{
private final Iterator<TSource> iteratorSource;
private final TransformProvider<TSource, TResult> selector;
private Iterator<TResult> currentIterator = null;
public SelectManyIterator(Iterator<TSource> source, TransformProvider<TSource, TResult> selector)
{
this.iteratorSource = source;
this.selector = selector;
loadNextIterator();
}
@Override
public boolean hasNext()
{
if(currentIteratorHasMore())
{
return true;
}
else if(currentIteratorIsEmptyButSourceHasMore())
{
loadNextIterator();
return hasNext();
}
else
{
return false;
}
}
@Override
public TResult next()
{
if(currentIteratorHasMore())
{
return currentIterator.next();
}
else if(currentIteratorIsEmptyButSourceHasMore())
{
loadNextIterator();
return next();
}
else
{
throw new NoSuchElementException();
}
}
@Override
public void remove()
{
throw new UnsupportedOperationException();
}
private boolean currentIteratorHasMore()
{
return this.currentIterator != null &&
this.currentIterator.hasNext();
}
private boolean currentIteratorIsEmptyButSourceHasMore()
{
return currentIterator != null &&
!currentIterator.hasNext() &&
iteratorSource.hasNext();
}
private void loadNextIterator()
{
if(this.iteratorSource.hasNext())
{
this.currentIterator = selector.selectInnerIterator(this.iteratorSource.next());
}
else
{
this.currentIterator = null;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment