package edu.berkeley.nlp.lm.collections;
import java.util.Iterator;
import edu.berkeley.nlp.lm.util.Pair;
/**
* Utilities for dealing with Iterators
*
* @author adampauls
*
*/
public class Iterators
{
/**
* Wraps an Iterator as an Iterable
*
* @param <T>
* @param it
* @return
*/
public static <T> Iterable<T> able(final Iterator<T> it) {
return new Iterable<T>()
{
boolean used = false;
@Override
public Iterator<T> iterator() {
if (used) throw new RuntimeException("One use iterable");
used = true;
return it;
}
};
}
public static <T> Iterable<T> flatten(final Iterator<Iterator<T>> iters) {
return Iterators.able(new IteratorIterator<T>(iters));
}
/**
* Wraps a two-level iteration scenario in an iterator. Each key of the keys
* iterator returns an iterator (via the factory) over T's.
* <p>
* The IteratorIterator loops through the iterator associated with each key
* until all the keys are used up.
*/
public static class IteratorIterator<T> implements Iterator<T>
{
Iterator<T> current = null;
private final Iterator<Iterator<T>> iters;
public IteratorIterator(final Iterator<Iterator<T>> iters) {
this.iters = iters;
current = getNextIterator();
}
private Iterator<T> getNextIterator() {
Iterator<T> next = null;
while (next == null) {
if (!iters.hasNext()) break;
next = iters.next();
if (!next.hasNext()) next = null;
}
return next;
}
@Override
public boolean hasNext() {
return current != null;
}
@Override
public T next() {
final T next = current.next();
if (!current.hasNext()) current = getNextIterator();
return next;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
/**
* Wraps a base iterator with a transformation function.
*/
public static abstract class Transform<S, T> implements Iterator<T>
{
private final Iterator<S> base;
public Transform(final Iterator<S> base) {
this.base = base;
}
@Override
public boolean hasNext() {
return base.hasNext();
}
@Override
public T next() {
return transform(base.next());
}
protected abstract T transform(S next);
@Override
public void remove() {
base.remove();
}
}
public static <S, T> Iterator<Pair<S, T>> zip(final Iterator<S> s, final Iterator<T> t) {
return new Iterator<Pair<S, T>>()
{
@Override
public boolean hasNext() {
return s.hasNext() && t.hasNext();
}
@Override
public Pair<S, T> next() {
return Pair.newPair(s.next(), t.next());
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}