All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.plumelib.util.CombinationIterator Maven / Gradle / Ivy

There is a newer version: 1.10.0
Show newest version
package org.plumelib.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import org.checkerframework.checker.index.qual.LengthOf;
import org.checkerframework.checker.lock.qual.GuardSatisfied;
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;

/**
 * Given a set of collections, yield each combination that takes one element from each collection.
 * Each tuple has a value from each candidate list. Each combination'slength is the same as the
 * number of input lists.
 *
 * 

For instance, given {@code [["a1", "a2"], ["b1"], ["c1", "c2", "c3"]]}, this class yields in * turn: * *

 *   ["a1", "b1", "c1"]
 *   ["a1", "b1", "c2"]
 *   ["a1", "b1", "c3"]
 *   ["a2", "b1", "c1"]
 *   ["a2", "b1", "c2"]
 *   ["a2", "b1", "c3"]
 * 
* * @param the type of the elements of the collections */ public class CombinationIterator implements Iterator> { /** Lists of candidate values for each position in generated lists. */ private final List[] listsOfCandidates; /** Iterators for each list of candidate values. */ private final Iterator[] iterators; /** The size of each returned result; the length of listsOfCandidates. */ private final @LengthOf({"listsOfCandidates", "iterators"}) int combinationSize; /** The next value to return, or null if to more values. */ private @Nullable List nextValue; /** * Creates a {@link CombinationIterator} for lists constructed from the given candidates. Each * generated list will be the same length as the given list. * * @param collectionsOfCandidates lists of candidate values for each position in generated lists */ @SuppressWarnings({"rawtypes", "unchecked"}) // for generic array creation public CombinationIterator(Collection> collectionsOfCandidates) { int size = collectionsOfCandidates.size(); // Just like collectionsOfCandidates, but indexable. @SuppressWarnings({"nullness:unneeded.suppression", "keyfor:argument"}) // temporary ArrayList> listOfCollectionsOfCanditates = new ArrayList<>(collectionsOfCandidates); listsOfCandidates = new ArrayList[size]; iterators = new Iterator[size]; combinationSize = size; nextValue = (combinationSize == 0 ? null : new ArrayList<>(collectionsOfCandidates.size())); for (int i = 0; i < combinationSize; i++) { Collection userSuppliedCandidates = listOfCollectionsOfCanditates.get(i); List candidates = new ArrayList<>(userSuppliedCandidates); listsOfCandidates[i] = candidates; Iterator it = candidates.iterator(); iterators[i] = it; if (nextValue != null) { if (it.hasNext()) { nextValue.add(it.next()); } else { nextValue = null; } } } } @Override @EnsuresNonNullIf(expression = "nextValue", result = true) public boolean hasNext(@GuardSatisfied CombinationIterator this) { return nextValue != null; } /** Advance {@code #nextValue} to the next value, or to null if there are no more values. */ @RequiresNonNull("nextValue") private void advanceNext(@GuardSatisfied CombinationIterator this) { List nnNextValue = nextValue; for (int i = combinationSize - 1; i >= 0; i--) { if (iterators[i].hasNext()) { nnNextValue.set(i, iterators[i].next()); return; } else { iterators[i] = listsOfCandidates[i].iterator(); nnNextValue.set(i, iterators[i].next()); } } nextValue = null; } @Override public List next(@GuardSatisfied CombinationIterator this) { if (!hasNext()) { throw new NoSuchElementException(); } List result = new ArrayList(nextValue); advanceNext(); return result; } @Override public void remove(@GuardSatisfied CombinationIterator this) { throw new UnsupportedOperationException( "Remove not implemented for randoop.reflection.SubstitutionEnumerator"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy