/*
* $Id$
*/
package edu.jas.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* Cartesian product with iterator.
* @author Heinz Kredel
*/
public class CartesianProduct implements Iterable> {
/**
* data structure.
*/
public final List> comps;
/**
* CartesianProduct constructor.
* @param comps components of the Cartesian product.
*/
public CartesianProduct(List> comps) {
if (comps == null) {
throw new IllegalArgumentException("null components not allowed");
}
this.comps = comps;
}
// /**
// * CartesianProduct constructor.
// * @param comps components of the Cartesian product.
// */
// public CartesianProduct(List> comps) {
// this( listToIterable(comps) );
// }
/**
* Get an iterator over subsets.
* @return an iterator.
*/
public Iterator> iterator() {
return new CartesianProductIterator(comps);
}
/**
* Transform list to iterables.
* @param comp components of the Cartesian product.
* @return iterables taken from lists.
*/
static List> listToIterable(List> comp) {
List> iter = new ArrayList>(comp.size());
for (List list : comp) {
iter.add(list);
}
return iter;
}
}
/**
* Cartesian product iterator.
* @author Heinz Kredel
*/
class CartesianProductIterator implements Iterator> {
/**
* data structure.
*/
final List> comps;
final List> compit;
List current;
boolean empty;
/**
* CartesianProduct iterator constructor.
* @param comps components of the Cartesian product.
*/
public CartesianProductIterator(List> comps) {
if (comps == null) {
throw new IllegalArgumentException("null comps not allowed");
}
this.comps = comps;
current = new ArrayList(comps.size());
compit = new ArrayList>(comps.size());
empty = false;
for (Iterable ci : comps) {
Iterator it = ci.iterator();
if (!it.hasNext()) {
empty = true;
current.clear();
break;
}
current.add(it.next());
compit.add(it);
}
//System.out.println("current = " + current);
}
/**
* Test for availability of a next tuple.
* @return true if the iteration has more tuples, else false.
*/
public synchronized boolean hasNext() {
return !empty;
}
/**
* Get next tuple.
* @return next tuple.
*/
public synchronized List next() {
if (empty) {
throw new NoSuchElementException("invalid call of next()");
}
List res = new ArrayList(current);
// search iterator which hasNext
int i = compit.size() - 1;
for (; i >= 0; i--) {
Iterator iter = compit.get(i);
if (iter.hasNext()) {
break;
}
}
if (i < 0) {
empty = true;
return res;
}
// update iterators
for (int j = i + 1; j < compit.size(); j++) {
Iterator iter = comps.get(j).iterator();
compit.set(j, iter);
}
// update current
for (int j = i; j < compit.size(); j++) {
Iterator iter = compit.get(j);
E el = iter.next();
current.set(j, el);
}
return res;
}
/**
* Remove a tuple if allowed.
*/
public void remove() {
throw new UnsupportedOperationException("cannnot remove tuples");
}
}
Ads help maintain this website.