public static <R> Stream<R> zip(final IntIterator a, final IntIterator b, final int valueForNoneA, final int valueForNoneB,
            final IntBiFunction<R> zipFunction) {
        return new IteratorStream<>(new ObjIteratorEx<R>() {
            @Override
            public boolean hasNext() {
                return a.hasNext() || b.hasNext();
            }

            @Override
            public R next() {
                if (hasNext() == false) {
                    throw new NoSuchElementException();
                }

                return zipFunction.apply(a.hasNext() ? a.nextInt() : valueForNoneA, b.hasNext() ? b.nextInt() : valueForNoneB);
            }
        });
    }
public static < R > Stream < R > zip ( final IntIterator a , final IntIterator b , final int valueForNoneA , final int valueForNoneB , final IntBiFunction < R > zipFunction ) { return new IteratorStream < > ( new ObjIteratorEx < R > ( ) { @ Override public boolean hasNext ( ) { return a . hasNext ( ) || b . hasNext ( ) ; } @ Override public R next ( ) { if ( hasNext ( ) == false ) { throw new NoSuchElementException ( ) ; } return zipFunction . apply ( a . hasNext ( ) ? a . nextInt ( ) : valueForNoneA , b . hasNext ( ) ? b . nextInt ( ) : valueForNoneB ) ; } } ) ; }
Zip together the "a" and "b" iterators until all of them runs out of values.
Each pair of values is combined into a single value using the supplied zipFunction function.

@param a
@param b
@param valueForNoneA value to fill if "a" runs out of values first.
@param valueForNoneB value to fill if "b" runs out of values first.
@param zipFunction
@return