src/main/java/io/reactivex/Observable.java
@SuppressWarnings({ "rawtypes", "unchecked" })
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public static <T, R> Observable<R> zip(ObservableSource<? extends ObservableSource<? extends T>> sources, final Function<? super Object[], ? extends R> zipper) {
        ObjectHelper.requireNonNull(zipper, "zipper is null");
        ObjectHelper.requireNonNull(sources, "sources is null");
        return RxJavaPlugins.onAssembly(new ObservableToList(sources, 16)
                .flatMap(ObservableInternalHelper.zipIterable(zipper)));
    }
@SuppressWarnings({ "rawtypes", "unchecked" })
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public static <T, R> Observable<R> zip(ObservableSource<? extends ObservableSource<? extends T>> sources, final Function<? super Object[], ? extends R> zipper) {
        ObjectHelper.requireNonNull(zipper, "zipper is null");
        ObjectHelper.requireNonNull(sources, "sources is null");
        return RxJavaPlugins.onAssembly(new ObservableToList(sources, 16)
                .flatMap(ObservableInternalHelper.zipIterable(zipper)));
    }
Returns an Observable that emits the results of a specified combiner function applied to combinations of
<i>n</i> items emitted, in sequence, by the <i>n</i> ObservableSources emitted by a specified ObservableSource.
<p>
{@code zip} applies this function in strict sequence, so the first item emitted by the new ObservableSource
will be the result of the function applied to the first item emitted by each of the ObservableSources emitted
by the source ObservableSource; the second item emitted by the new ObservableSource will be the result of the
function applied to the second item emitted by each of those ObservableSources; and so forth.
<p>
The resulting {@code ObservableSource<R>} returned from {@code zip} will invoke {@code onNext} as many times as
the number of {@code onNext} invocations of the source ObservableSource that emits the fewest items.
<p>
The operator subscribes to its sources in order they are specified and completes eagerly if
one of the sources is shorter than the rest while disposing the other sources. Therefore, it
is possible those other sources will never be able to run to completion (and thus not calling
{@code doOnComplete()}). This can also happen if the sources are exactly the same length; if
source A completes and B has been consumed and is about to complete, the operator detects A won't
be sending further values and it will dispose B immediately. For example:
<pre><code>zip(just(range(1, 5).doOnComplete(action1), range(6, 5).doOnComplete(action2)), (a) -&gt; a)</code></pre>
{@code action1} will be called but {@code action2} won't.
<br>To work around this termination property,
use {@link #doOnDispose(Action)} as well or use {@code using()} to do cleanup in case of completion
or a dispose() call.
<p>
Note on method signature: since Java doesn't allow creating a generic array with {@code new T[]}, the
implementation of this operator has to create an {@code Object[]} instead. Unfortunately, a
{@code Function<Integer[], R>} passed to the method would trigger a {@code ClassCastException}.

<p>
<img width="640" height="370" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/zip.o.png" alt="">
<dl>
<dt><b>Scheduler:</b></dt>
<dd>{@code zip} does not operate by default on a particular {@link Scheduler}.</dd>
</dl>

@param <T> the value type of the inner ObservableSources
@param <R> the zipped result type
@param sources
an ObservableSource of source ObservableSources
@param zipper
a function that, when applied to an item emitted by each of the ObservableSources emitted by
{@code ws}, results in an item that will be emitted by the resulting ObservableSource
@return an Observable that emits the zipped results
@see <a href="http://reactivex.io/documentation/operators/zip.html">ReactiveX operators documentation: Zip</a>