I have the following collection type:
Map> map;
I would like to create unique combinations of each o
I wrote a class implementing Iterable
, and holding only the current item in memory. The Iterable as well as the Iterator can be converted to a Stream
if desired.
class CartesianProduct implements Iterable> {
private final Iterable extends Iterable> factors;
public CartesianProduct(final Iterable extends Iterable> factors) {
this.factors = factors;
}
@Override
public Iterator> iterator() {
return new CartesianProductIterator<>(factors);
}
}
class CartesianProductIterator implements Iterator> {
private final List> factors;
private final Stack> iterators;
private final Stack current;
private List next;
private int index = 0;
private void computeNext() {
while (true) {
if (iterators.get(index).hasNext()) {
current.add(iterators.get(index).next());
if (index == factors.size() - 1) {
next = new ArrayList<>(current);
current.pop();
return;
}
index++;
iterators.add(factors.get(index).iterator());
} else {
index--;
if (index < 0) {
return;
}
iterators.pop();
current.pop();
}
}
}
public CartesianProductIterator(final Iterable extends Iterable> factors) {
this.factors = StreamSupport.stream(factors.spliterator(), false)
.collect(Collectors.toList());
if (this.factors.size() == 0) {
index = -1;
}
iterators = new Stack<>();
iterators.add(this.factors.get(0).iterator());
current = new Stack<>();
computeNext();
}
@Override
public boolean hasNext() {
if (next == null && index >= 0) {
computeNext();
}
return next != null;
}
@Override
public List next() {
if (!hasNext()) {
throw new IllegalStateException();
}
var result = next;
next = null;
return result;
}
}