package org.jcommons.type; import java.io.IOException; import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.ArrayBlockingQueue; public class Iterators { public static <T> void fillList(Iterator<? extends T> it, List<T> lst) { while (it.hasNext()) { lst.add(it.next()); } } public static <T> List<T> fillList(Iterator<? extends T> it) { List<T> lst = new ArrayList<T>(); fillList(it, lst); return lst; } /** * WraTps a base iterator with a transformation function. */ public static abstract class Transform<S, T> implements Iterator<T> { private Iterator<S> base; public Transform(Iterator<S> base) { this.base = base; } public boolean hasNext() { return base.hasNext(); } public T next() { return transform(base.next()); } protected abstract T transform(S next); public void remove() { base.remove(); } } private Iterators() { } /** * Wraps an iterator as an iterable * * @param <T> * @param it * @return */ public static <T> Iterable<T> newIterable(final Iterator<T> it) { return new Iterable<T>() { public Iterator<T> iterator() { return it; } }; } /** * 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; public Iterator<T> iterator() { if (used) throw new RuntimeException("One use iterable"); used = true; return it; } }; } /** * Executes calls to next() in a different thread * * @param <T> * @param base * @param numThreads * @return */ public static <T> Iterator<T> thread(final Iterator<T> base) { return new Iterator<T>() { ArrayBlockingQueue<T> els = new ArrayBlockingQueue<T>(2); private boolean finishedLoading = false; private boolean running = false; Thread thread = new Thread(new Runnable() { public void run() { while (base.hasNext()) { try { els.put(base.next()); } catch (InterruptedException e) { throw new RuntimeException(e); } } finishedLoading = true; } }); public boolean hasNext() { return !(finishedLoading && els.isEmpty()); } public T next() { if (!running) thread.start(); running = true; try { return els.take(); } catch (InterruptedException e) { throw new RuntimeException(e); } } public void remove() { throw new UnsupportedOperationException(); } }; } public static <S, T> Iterator<Pair<S, T>> zip(final Iterator<S> s, final Iterator<T> t) { return new Iterator<Pair<S, T>>() { public boolean hasNext() { return s.hasNext() && t.hasNext(); } public Pair<S, T> next() { return Pair.newPair(s.next(), t.next()); } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Provides a max number of elements for an underlying base iterator. */ public static <T> Iterator<T> maxLengthIterator(final Iterator<T> base, final int max) { return new Iterator<T>() { int count = 0; public boolean hasNext() { return base.hasNext() && count < max; } public T next() { if (!hasNext()) throw new NoSuchElementException("No more elements"); count++; return base.next(); } public void remove() { throw new UnsupportedOperationException(); // TODO Maybe this should behave in a more friendly manner } }; } /** * Wraps a two-level iteration scenario in an iterator. Each key of the keys * iterator returns an iterator (via the factory) over T's. * * 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; Iterator keys; Factory<Iterator<T>> iterFactory; public IteratorIterator(Iterator keys, Factory<Iterator<T>> iterFactory) { this.keys = keys; this.iterFactory = iterFactory; current = getNextIterator(); } private Iterator<T> getNextIterator() { Iterator<T> next = null; while (next == null) { if (!keys.hasNext()) break; next = iterFactory.newInstance(keys.next()); if (!next.hasNext()) next = null; } return next; } public boolean hasNext() { return current != null; } public T next() { T next = current.next(); if (!current.hasNext()) current = getNextIterator(); return next; } public void remove() { throw new UnsupportedOperationException(); } } /** * Creates an iterator that only returns items of a base iterator that pass * a filter. * * Null items cannot be returned from the base iterator. */ public static class FilteredIterator<T> implements Iterator<T> { Filter<T> filter; T next; private Iterator<T> base; public FilteredIterator(Filter<T> filter, Iterator<T> base) { super(); this.filter = filter; this.base = base; loadNext(); } public FilteredIterator(Filter<T> filter, Iterable<T> items) { this(filter, items.iterator()); } private void loadNext() { next = null; while (next == null && base.hasNext()) { next = base.next(); if (!filter.accept(next)) next = null; } } public boolean hasNext() { return next != null; } public T next() { T old = next; loadNext(); return old; } public void remove() { throw new UnsupportedOperationException(); } } public static class TransformingIterator<I, O> implements Iterator<O> { private MyMethod<I, O> transformer; private Iterator<I> inputIterator; public TransformingIterator(Iterator<I> inputIterator, MyMethod<I, O> transformer) { this.inputIterator = inputIterator; this.transformer = transformer; } public boolean hasNext() { return inputIterator.hasNext(); } public O next() { return transformer.call(inputIterator.next()); } public void remove() { inputIterator.remove(); } } public static <T> Iterator<T> filter(Iterator<T> iterator, Filter<T> filter) { return new FilteredIterator<T>(filter, iterator); } public static <T> Iterator<T> concat(Iterable<Iterator<? extends T>> args) { Factory<Iterator<T>> factory = new Factory<Iterator<T>>() { public Iterator<T> newInstance(Object... args) { return (Iterator<T>) args[0]; } }; return new IteratorIterator<T>(Arrays.asList(args).iterator(), factory); } public static <T> Iterator<T> concat(Iterator<? extends T>... args) { Factory<Iterator<T>> factory = new Factory<Iterator<T>>() { public Iterator<T> newInstance(Object... args) { return (Iterator<T>) args[0]; } }; return new IteratorIterator<T>(Arrays.asList(args).iterator(), factory); } public static <U> Iterator<U> oneItemIterator(final U item) { return new Iterator<U>() { boolean unused = true; public boolean hasNext() { return unused; } public U next() { unused = false; return item; } public void remove() { throw new UnsupportedOperationException(); } }; } public static Iterator emptyIterator() { return new Iterator() { public boolean hasNext() { return false; } public Object next() { throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); } }; } public static <T> Iterable<T> concat(Iterable<T> a, Iterable<T> b) { return able(concat(a.iterator(), b.iterator())); } public static <T> List<T> nextList(List<Iterator<T>> iterators) { List<T> items = new ArrayList<T>(iterators.size()); for (Iterator<T> iter : iterators) { items.add(iter.next()); } return items; } public static Iterator<Object> objectIterator( final ObjectInputStream instream) { return new Iterator<Object>() { Object next = softRead(); public boolean hasNext() { return next != null; } private Object softRead() { try { return instream.readObject(); } catch (IOException e) { return null; } catch (ClassNotFoundException e) { return null; } } public Object next() { Object curr = next; next = softRead(); return curr; } public void remove() { throw new UnsupportedOperationException(); } }; } }