How can I make Cartesian product with Java 8 streams?

后端 未结 9 755
谎友^
谎友^ 2020-11-28 08:10

I have the following collection type:

Map> map;

I would like to create unique combinations of each o

9条回答
  •  情深已故
    2020-11-28 08:41

    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> factors;
    
        public CartesianProduct(final 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> 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;
        }
    }
    

提交回复
热议问题