code: public static <T, R> Stream<R> zip(final Collection<? extends Stream<? extends T>> c, final List<? extends T> valuesForNone,
              final Function<? super List<? extends T>, R> zipFunction) {
          if (N.isNullOrEmpty(c)) {
              return Stream.empty();
          }
  
          final int len = c.size();
  
          if (len != valuesForNone.size()) {
              throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators");
          }
  
          final Stream<? extends T>[] ss = c.toArray(new Stream[len]);
          final ObjIterator<? extends T>[] iters = new ObjIterator[len];
  
          for (int i = 0; i < len; i++) {
              iters[i] = ss[i].iteratorEx();
          }
  
          return new IteratorStream<>(new ObjIteratorEx<R>() {
              @Override
              public boolean hasNext() {
                  for (int i = 0; i < len; i++) {
                      if (iters[i] != null) {
                          if (iters[i].hasNext()) {
                              return true;
                          } else if (iters[i] != null) {
                              iters[i] = null;
                              ss[i].close();
                          }
                      }
                  }
  
                  return false;
              }
  
              @Override
              public R next() {
                  final Object[] args = new Object[len];
                  boolean hasNext = false;
  
                  for (int i = 0; i < len; i++) {
                      if (iters[i] != null && iters[i].hasNext()) {
                          hasNext = true;
                          args[i] = iters[i].next();
                      } else {
                          args[i] = valuesForNone.get(i);
                      }
                  }
  
                  if (hasNext == false) {
                      throw new NoSuchElementException();
                  }
  
                  return zipFunction.apply(Arrays.asList((T[]) args));
              }
          });
      }
docs: Zip together the iterators until all of them runs out of values.
  Each array of values is combined into a single value using the supplied zipFunction function.
  
  @param c
  @param valuesForNone value to fill for any iterator runs out of values.
  @param zipFunction
  @return