Iterative Cartesian Product in Java

前端 未结 9 1897
既然无缘
既然无缘 2020-11-27 07:00

I want to compute the cartesian product of an arbitrary number of nonempty sets in Java.

I\'ve wrote that iterative code...

public s         


        
9条回答
  •  忘掉有多难
    2020-11-27 07:34

    Here is a lazy iterator approach that uses a function to produce an appropriate output type.

      public static  Iterable cartesianProduct(
          final Function fn, Object[]... options) {
        final Object[][] opts = new Object[options.length][];
        for (int i = opts.length; --i >= 0;) {
          // NPE on null input collections, and handle the empty output case here
          // since the iterator code below assumes that it is not exhausted the
          // first time through fetch.
          if (options[i].length == 0) { return Collections.emptySet(); }
          opts[i] = options[i].clone();
        }
        return new Iterable() {
          public Iterator iterator() {
            return new Iterator() {
              final int[] pos = new int[opts.length];
              boolean hasPending;
              T pending;
              boolean exhausted;
    
              public boolean hasNext() {
                fetch();
                return hasPending;
              }
    
              public T next() {
                fetch();
                if (!hasPending) { throw new NoSuchElementException(); }
                T out = pending;
                pending = null;  // release for GC
                hasPending = false;
                return out;
              }
    
              public void remove() { throw new UnsupportedOperationException(); }
    
              private void fetch() {
                if (hasPending || exhausted) { return; }
                // Produce a result.
                int n = pos.length;
                Object[] args = new Object[n];
                for (int j = n; --j >= 0;) { args[j] = opts[j][pos[j]]; }
                pending = fn.apply(args);
                hasPending = true;
                // Increment to next.
                for (int i = n; --i >= 0;) {
                  if (++pos[i] < opts[i].length) {
                    for (int j = n; --j > i;) { pos[j] = 0; }
                    return;
                  }
                }
                exhausted = true;
              }
            };
          }
        };
      }
    

提交回复
热议问题