package org.magenta.random; import java.util.Iterator; import java.util.List; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; /** * A composite {@link Iterable} that iterates through a list of iterables randomly giving the impression that the data is shuffled. * * @author ngagnon * * @param <D> the type of data being iterated */ public class MixedIterable<D> implements Iterable<D> { private final Iterable<? extends Iterable<? extends D>> iterables; private final FluentRandom randomizer; MixedIterable(Iterable<? extends Iterable<? extends D>> iterables, FluentRandom randomizer) { this.iterables = iterables; this.randomizer = randomizer; } @Override public Iterator<D> iterator() { return new RandomlyMixedIterator(iterables); } private class RandomlyMixedIterator implements Iterator<D> { private final List<Iterator<? extends D>> iterators; private RandomlyMixedIterator(Iterable<? extends Iterable<? extends D>> iterables) { this.iterators = Lists.newArrayList(); for (Iterable<? extends D> it : iterables) { if (!Iterables.isEmpty(it)) { iterators.add(it.iterator()); } } } @Override public boolean hasNext() { return !iterators.isEmpty(); } @Override public D next() { Iterator<? extends D> iterator = randomizer.iterable(iterators).any(); D e = iterator.next(); if (!iterator.hasNext()) { iterators.remove(iterator); } return e; } @Override public void remove() { throw new UnsupportedOperationException("remove not supported on RandomlyMixedIterable"); } } }