From 0c84f4017f576bd250e4408d8410f6647507027c Mon Sep 17 00:00:00 2001 From: David Karnok Date: Tue, 21 Jan 2020 14:26:15 +0100 Subject: [PATCH 01/37] 3.x: Fix method argument naming across types (#6853) * 3.x: Fix method argument naming across types * Remove outdated null-test of blockingMostRecent --- .../reactivex/rxjava3/core/Completable.java | 152 +++++----- .../io/reactivex/rxjava3/core/Flowable.java | 148 +++++----- .../java/io/reactivex/rxjava3/core/Maybe.java | 111 ++++---- .../io/reactivex/rxjava3/core/Observable.java | 269 +++++++++--------- .../io/reactivex/rxjava3/core/Single.java | 154 +++++----- .../BlockingFlowableMostRecentTest.java | 4 - .../BlockingObservableMostRecentTest.java | 4 - .../internal/util/OperatorArgumentNaming.java | 169 +++++++++++ .../ParamValidationCheckerTest.java | 6 - .../validators/ParamValidationNaming.java | 2 +- 10 files changed, 591 insertions(+), 428 deletions(-) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/util/OperatorArgumentNaming.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index ee3af955a9..1266255315 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -332,21 +332,21 @@ public static Completable create(@NonNull CompletableOnSubscribe source) { *
Scheduler:
*
{@code unsafeCreate} does not operate by default on a particular {@link Scheduler}.
* - * @param source the callback which will receive the {@link CompletableObserver} instances + * @param onSubscribe the callback which will receive the {@link CompletableObserver} instances * when the {@code Completable} is subscribed to. * @return the new {@code Completable} instance - * @throws NullPointerException if {@code source} is {@code null} + * @throws NullPointerException if {@code onSubscribe} is {@code null} * @throws IllegalArgumentException if {@code source} is a {@code Completable} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable unsafeCreate(@NonNull CompletableSource source) { - Objects.requireNonNull(source, "source is null"); - if (source instanceof Completable) { + public static Completable unsafeCreate(@NonNull CompletableSource onSubscribe) { + Objects.requireNonNull(onSubscribe, "onSubscribe is null"); + if (onSubscribe instanceof Completable) { throw new IllegalArgumentException("Use of unsafeCreate(Completable)!"); } - return RxJavaPlugins.onAssembly(new CompletableFromUnsafeSource(source)); + return RxJavaPlugins.onAssembly(new CompletableFromUnsafeSource(onSubscribe)); } /** @@ -357,16 +357,16 @@ public static Completable unsafeCreate(@NonNull CompletableSource source) { *
Scheduler:
*
{@code defer} does not operate by default on a particular {@link Scheduler}.
* - * @param completableSupplier the supplier that returns the {@code Completable} that will be subscribed to. + * @param supplier the supplier that returns the {@code Completable} that will be subscribed to. * @return the new {@code Completable} instance - * @throws NullPointerException if {@code completableSupplier} is {@code null} + * @throws NullPointerException if {@code supplier} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable defer(@NonNull Supplier completableSupplier) { - Objects.requireNonNull(completableSupplier, "completableSupplier is null"); - return RxJavaPlugins.onAssembly(new CompletableDefer(completableSupplier)); + public static Completable defer(@NonNull Supplier supplier) { + Objects.requireNonNull(supplier, "supplier is null"); + return RxJavaPlugins.onAssembly(new CompletableDefer(supplier)); } /** @@ -381,16 +381,16 @@ public static Completable defer(@NonNull Supplier c *
Scheduler:
*
{@code error} does not operate by default on a particular {@link Scheduler}.
* - * @param errorSupplier the error supplier, not {@code null} + * @param supplier the error supplier, not {@code null} * @return the new {@code Completable} instance - * @throws NullPointerException if {@code errorSupplier} is {@code null} + * @throws NullPointerException if {@code supplier} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable error(@NonNull Supplier errorSupplier) { - Objects.requireNonNull(errorSupplier, "errorSupplier is null"); - return RxJavaPlugins.onAssembly(new CompletableErrorSupplier(errorSupplier)); + public static Completable error(@NonNull Supplier supplier) { + Objects.requireNonNull(supplier, "supplier is null"); + return RxJavaPlugins.onAssembly(new CompletableErrorSupplier(supplier)); } /** @@ -401,16 +401,16 @@ public static Completable error(@NonNull Supplier errorSupp *
Scheduler:
*
{@code error} does not operate by default on a particular {@link Scheduler}.
* - * @param error the {@code Throwable} instance to emit, not {@code null} + * @param throwable the {@code Throwable} instance to emit, not {@code null} * @return the new {@code Completable} instance - * @throws NullPointerException if {@code error} is {@code null} + * @throws NullPointerException if {@code throwable} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable error(@NonNull Throwable error) { - Objects.requireNonNull(error, "error is null"); - return RxJavaPlugins.onAssembly(new CompletableError(error)); + public static Completable error(@NonNull Throwable throwable) { + Objects.requireNonNull(throwable, "throwable is null"); + return RxJavaPlugins.onAssembly(new CompletableError(throwable)); } /** @@ -429,16 +429,16 @@ public static Completable error(@NonNull Throwable error) { * {@link RxJavaPlugins#onError(Throwable)} as an {@link io.reactivex.rxjava3.exceptions.UndeliverableException UndeliverableException}. * * - * @param run the {@code Action} to run for each subscribing {@link CompletableObserver} + * @param action the {@code Action} to run for each subscribing {@link CompletableObserver} * @return the new {@code Completable} instance - * @throws NullPointerException if {@code run} is {@code null} + * @throws NullPointerException if {@code action} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Completable fromAction(@NonNull Action run) { - Objects.requireNonNull(run, "run is null"); - return RxJavaPlugins.onAssembly(new CompletableFromAction(run)); + public static Completable fromAction(@NonNull Action action) { + Objects.requireNonNull(action, "action is null"); + return RxJavaPlugins.onAssembly(new CompletableFromAction(action)); } /** @@ -1029,19 +1029,19 @@ private static NullPointerException toNpe(Throwable ex) { * * @param the resource type * @param resourceSupplier the {@link Supplier} that returns a resource to be managed. - * @param completableFunction the {@link Function} that given a resource returns a {@code CompletableSource} instance that will be subscribed to - * @param disposer the {@link Consumer} that disposes the resource created by the resource supplier + * @param sourceSupplier the {@link Function} that given a resource returns a {@code CompletableSource} instance that will be subscribed to + * @param resourceCleanup the {@link Consumer} that disposes the resource created by the resource supplier * @return the new {@code Completable} instance - * @throws NullPointerException if {@code resourceSupplier}, {@code completableFunction} - * or {@code disposer} is {@code null} + * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} + * or {@code resourceCleanup} is {@code null} */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull public static Completable using(@NonNull Supplier resourceSupplier, - @NonNull Function completableFunction, - @NonNull Consumer disposer) { - return using(resourceSupplier, completableFunction, disposer, true); + @NonNull Function sourceSupplier, + @NonNull Consumer resourceCleanup) { + return using(resourceSupplier, sourceSupplier, resourceCleanup, true); } /** @@ -1059,31 +1059,31 @@ public static Completable using(@NonNull Supplier resourceSupplier, * * @param the resource type * @param resourceSupplier the {@link Supplier} that returns a resource to be managed - * @param completableFunction the {@link Function} that given a resource returns a non-{@code null} + * @param sourceSupplier the {@link Function} that given a resource returns a non-{@code null} * {@code CompletableSource} instance that will be subscribed to - * @param disposer the {@link Consumer} that disposes the resource created by the resource supplier + * @param resourceCleanup the {@link Consumer} that disposes the resource created by the resource supplier * @param eager * If {@code true} then resource disposal will happen either on a {@code dispose()} call before the upstream is disposed * or just before the emission of a terminal event ({@code onComplete} or {@code onError}). * If {@code false} the resource disposal will happen either on a {@code dispose()} call after the upstream is disposed * or just after the emission of a terminal event ({@code onComplete} or {@code onError}). * @return the new {@code Completable} instance - * @throws NullPointerException if {@code resourceSupplier}, {@code completableFunction} - * or {@code disposer} is {@code null} + * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} + * or {@code resourceCleanup} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) public static Completable using( @NonNull Supplier resourceSupplier, - @NonNull Function completableFunction, - @NonNull Consumer disposer, + @NonNull Function sourceSupplier, + @NonNull Consumer resourceCleanup, boolean eager) { Objects.requireNonNull(resourceSupplier, "resourceSupplier is null"); - Objects.requireNonNull(completableFunction, "completableFunction is null"); - Objects.requireNonNull(disposer, "disposer is null"); + Objects.requireNonNull(sourceSupplier, "sourceSupplier is null"); + Objects.requireNonNull(resourceCleanup, "resourceCleanup is null"); - return RxJavaPlugins.onAssembly(new CompletableUsing<>(resourceSupplier, completableFunction, disposer, eager)); + return RxJavaPlugins.onAssembly(new CompletableUsing<>(resourceSupplier, sourceSupplier, resourceCleanup, eager)); } /** @@ -1390,7 +1390,7 @@ public final Completable concatWith(@NonNull CompletableSource other) { *
Scheduler:
*
{@code delay} does operate by default on the {@code computation} {@link Scheduler}.
* - * @param delay the delay time + * @param time the delay time * @param unit the delay unit * @return the new {@code Completable} instance * @throws NullPointerException if {@code unit} is {@code null} @@ -1398,8 +1398,8 @@ public final Completable concatWith(@NonNull CompletableSource other) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Completable delay(long delay, @NonNull TimeUnit unit) { - return delay(delay, unit, Schedulers.computation(), false); + public final Completable delay(long time, @NonNull TimeUnit unit) { + return delay(time, unit, Schedulers.computation(), false); } /** @@ -1411,7 +1411,7 @@ public final Completable delay(long delay, @NonNull TimeUnit unit) { *
Scheduler:
*
{@code delay} operates on the {@code Scheduler} you specify.
* - * @param delay the delay time + * @param time the delay time * @param unit the delay unit * @param scheduler the {@code Scheduler} to run the delayed completion on * @return the new {@code Completable} instance @@ -1420,8 +1420,8 @@ public final Completable delay(long delay, @NonNull TimeUnit unit) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Completable delay(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { - return delay(delay, unit, scheduler, false); + public final Completable delay(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + return delay(time, unit, scheduler, false); } /** @@ -1433,7 +1433,7 @@ public final Completable delay(long delay, @NonNull TimeUnit unit, @NonNull Sche *
Scheduler:
*
{@code delay} operates on the {@code Scheduler} you specify.
* - * @param delay the delay time + * @param time the delay time * @param unit the delay unit * @param scheduler the {@code Scheduler} to run the delayed completion on * @param delayError delay the error emission as well? @@ -1443,10 +1443,10 @@ public final Completable delay(long delay, @NonNull TimeUnit unit, @NonNull Sche @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Completable delay(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean delayError) { + public final Completable delay(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean delayError) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new CompletableDelay(this, delay, unit, scheduler, delayError)); + return RxJavaPlugins.onAssembly(new CompletableDelay(this, time, unit, scheduler, delayError)); } /** @@ -1459,7 +1459,7 @@ public final Completable delay(long delay, @NonNull TimeUnit unit, @NonNull Sche * *

History: 2.2.3 - experimental * - * @param delay the time to delay the subscription + * @param time the time to delay the subscription * @param unit the time unit of {@code delay} * @return the new {@code Completable} instance * @throws NullPointerException if {@code unit} is {@code null} @@ -1469,8 +1469,8 @@ public final Completable delay(long delay, @NonNull TimeUnit unit, @NonNull Sche @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Completable delaySubscription(long delay, @NonNull TimeUnit unit) { - return delaySubscription(delay, unit, Schedulers.computation()); + public final Completable delaySubscription(long time, @NonNull TimeUnit unit) { + return delaySubscription(time, unit, Schedulers.computation()); } /** @@ -1483,7 +1483,7 @@ public final Completable delaySubscription(long delay, @NonNull TimeUnit unit) { *

You specify which {@code Scheduler} this operator will use.
* *

History: 2.2.3 - experimental - * @param delay the time to delay the subscription + * @param time the time to delay the subscription * @param unit the time unit of {@code delay} * @param scheduler the {@code Scheduler} on which the waiting and subscription will happen * @return the new {@code Completable} instance @@ -1494,8 +1494,8 @@ public final Completable delaySubscription(long delay, @NonNull TimeUnit unit) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Completable delaySubscription(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { - return Completable.timer(delay, unit, scheduler).andThen(this); + public final Completable delaySubscription(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + return Completable.timer(time, unit, scheduler).andThen(this); } /** @@ -1974,17 +1974,17 @@ public final Completable onErrorComplete(@NonNull Predicate p *

Scheduler:
*
{@code onErrorResumeNext} does not operate by default on a particular {@link Scheduler}.
* - * @param errorMapper the {@code mapper} {@code Function} that takes the error and should return a {@code CompletableSource} as + * @param fallbackSupplier the {@code mapper} {@code Function} that takes the error and should return a {@code CompletableSource} as * continuation. * @return the new {@code Completable} instance - * @throws NullPointerException if {@code errorMapper} is {@code null} + * @throws NullPointerException if {@code fallbackSupplier} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Completable onErrorResumeNext(@NonNull Function errorMapper) { - Objects.requireNonNull(errorMapper, "errorMapper is null"); - return RxJavaPlugins.onAssembly(new CompletableResumeNext(this, errorMapper)); + public final Completable onErrorResumeNext(@NonNull Function fallbackSupplier) { + Objects.requireNonNull(fallbackSupplier, "fallbackSupplier is null"); + return RxJavaPlugins.onAssembly(new CompletableResumeNext(this, fallbackSupplier)); } /** @@ -2544,16 +2544,16 @@ public final Completable timeout(long timeout, @NonNull TimeUnit unit) { * * @param timeout the timeout value * @param unit the unit of {@code timeout} - * @param other the other {@code CompletableSource} instance to switch to in case of a timeout + * @param fallback the other {@code CompletableSource} instance to switch to in case of a timeout * @return the new {@code Completable} instance - * @throws NullPointerException if {@code unit} or {@code other} is {@code null} + * @throws NullPointerException if {@code unit} or {@code fallback} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.COMPUTATION) - public final Completable timeout(long timeout, @NonNull TimeUnit unit, @NonNull CompletableSource other) { - Objects.requireNonNull(other, "other is null"); - return timeout0(timeout, unit, Schedulers.computation(), other); + public final Completable timeout(long timeout, @NonNull TimeUnit unit, @NonNull CompletableSource fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return timeout0(timeout, unit, Schedulers.computation(), fallback); } /** @@ -2593,16 +2593,16 @@ public final Completable timeout(long timeout, @NonNull TimeUnit unit, @NonNull * @param timeout the timeout value * @param unit the unit of {@code timeout} * @param scheduler the {@code Scheduler} to use to wait for completion - * @param other the other {@code Completable} instance to switch to in case of a timeout + * @param fallback the other {@code Completable} instance to switch to in case of a timeout * @return the new {@code Completable} instance - * @throws NullPointerException if {@code unit}, {@code scheduler} or {@code other} is {@code null} + * @throws NullPointerException if {@code unit}, {@code scheduler} or {@code fallback} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Completable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull CompletableSource other) { - Objects.requireNonNull(other, "other is null"); - return timeout0(timeout, unit, scheduler, other); + public final Completable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull CompletableSource fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return timeout0(timeout, unit, scheduler, fallback); } /** @@ -2616,18 +2616,18 @@ public final Completable timeout(long timeout, @NonNull TimeUnit unit, @NonNull * @param timeout the timeout value * @param unit the unit of {@code timeout} * @param scheduler the {@code Scheduler} to use to wait for completion - * @param other the other {@code Completable} instance to switch to in case of a timeout, + * @param fallback the other {@code Completable} instance to switch to in case of a timeout, * if {@code null} a {@link TimeoutException} is emitted instead * @return the new {@code Completable} instance - * @throws NullPointerException if {@code unit}, {@code scheduler} or {@code other} is {@code null} + * @throws NullPointerException if {@code unit}, {@code scheduler} or {@code fallback} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.CUSTOM) - private Completable timeout0(long timeout, TimeUnit unit, Scheduler scheduler, CompletableSource other) { + private Completable timeout0(long timeout, TimeUnit unit, Scheduler scheduler, CompletableSource fallback) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new CompletableTimeout(this, timeout, unit, scheduler, other)); + return RxJavaPlugins.onAssembly(new CompletableTimeout(this, timeout, unit, scheduler, fallback)); } /** diff --git a/src/main/java/io/reactivex/rxjava3/core/Flowable.java b/src/main/java/io/reactivex/rxjava3/core/Flowable.java index 54bc24fca0..038c3f680b 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Flowable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Flowable.java @@ -2178,9 +2178,9 @@ public static Flowable error(@NonNull Throwable throwable) { *
{@code fromPublisher} does not operate by default on a particular {@link Scheduler}.
* * @param the value type of the flow - * @param source the {@code Publisher} to convert + * @param publisher the {@code Publisher} to convert * @return the new {@code Flowable} instance - * @throws NullPointerException if the {@code source} {@code Publisher} is {@code null} + * @throws NullPointerException if {@code publisher} is {@code null} * @see #create(FlowableOnSubscribe, BackpressureStrategy) */ @CheckReturnValue @@ -2188,13 +2188,13 @@ public static Flowable error(@NonNull Throwable throwable) { @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings("unchecked") - public static Flowable fromPublisher(@NonNull Publisher<@NonNull ? extends T> source) { - if (source instanceof Flowable) { - return RxJavaPlugins.onAssembly((Flowable)source); + public static Flowable fromPublisher(@NonNull Publisher<@NonNull ? extends T> publisher) { + if (publisher instanceof Flowable) { + return RxJavaPlugins.onAssembly((Flowable)publisher); } - Objects.requireNonNull(source, "source is null"); + Objects.requireNonNull(publisher, "publisher is null"); - return RxJavaPlugins.onAssembly(new FlowableFromPublisher<>(source)); + return RxJavaPlugins.onAssembly(new FlowableFromPublisher<>(publisher)); } /** @@ -4514,10 +4514,10 @@ public static Flowable unsafeCreate(@NonNull Publisher onSubscribe) { * the factory function to create a resource object that depends on the {@code Publisher} * @param sourceSupplier * the factory function to create a {@code Publisher} - * @param resourceDisposer + * @param resourceCleanup * the function that will dispose of the resource * @return the new {@code Flowable} instance - * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} or {@code resourceDisposer} is {@code null} + * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} or {@code resourceCleanup} is {@code null} * @see ReactiveX operators documentation: Using */ @CheckReturnValue @@ -4527,8 +4527,8 @@ public static Flowable unsafeCreate(@NonNull Publisher onSubscribe) { public static Flowable using( @NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, - @NonNull Consumer resourceDisposer) { - return using(resourceSupplier, sourceSupplier, resourceDisposer, true); + @NonNull Consumer resourceCleanup) { + return using(resourceSupplier, sourceSupplier, resourceCleanup, true); } /** @@ -4551,7 +4551,7 @@ public static Flowable using( * the factory function to create a resource object that depends on the {@code Publisher} * @param sourceSupplier * the factory function to create a {@code Publisher} - * @param resourceDisposer + * @param resourceCleanup * the function that will dispose of the resource * @param eager * If {@code true}, the resource disposal will happen either on a {@code cancel()} call before the upstream is disposed @@ -4559,7 +4559,7 @@ public static Flowable using( * If {@code false} the resource disposal will happen either on a {@code cancel()} call after the upstream is disposed * or just after the emission of a terminal event ({@code onComplete} or {@code onError}). * @return the new {@code Flowable} instance - * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} or {@code resourceDisposer} is {@code null} + * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} or {@code resourceCleanup} is {@code null} * @see ReactiveX operators documentation: Using * @since 2.0 */ @@ -4570,12 +4570,12 @@ public static Flowable using( public static Flowable using( @NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, - @NonNull Consumer resourceDisposer, + @NonNull Consumer resourceCleanup, boolean eager) { Objects.requireNonNull(resourceSupplier, "resourceSupplier is null"); Objects.requireNonNull(sourceSupplier, "sourceSupplier is null"); - Objects.requireNonNull(resourceDisposer, "resourceDisposer is null"); - return RxJavaPlugins.onAssembly(new FlowableUsing(resourceSupplier, sourceSupplier, resourceDisposer, eager)); + Objects.requireNonNull(resourceCleanup, "resourceCleanup is null"); + return RxJavaPlugins.onAssembly(new FlowableUsing(resourceSupplier, sourceSupplier, resourceCleanup, eager)); } /** @@ -5944,6 +5944,7 @@ public final Iterable blockingLatest() { * the initial item that the {@code Iterable} sequence will yield if this * {@code Flowable} has not yet emitted an item * @return the new {@code Iterable} instance + * @throws NullPointerException if {@code initialItem} is {@code null} * @see ReactiveX documentation: First */ @CheckReturnValue @@ -5951,6 +5952,7 @@ public final Iterable blockingLatest() { @SchedulerSupport(SchedulerSupport.NONE) @NonNull public final Iterable blockingMostRecent(@NonNull T initialItem) { + Objects.requireNonNull(initialItem, "initialItem is null"); return new BlockingFlowableMostRecent<>(this, initialItem); } @@ -8616,7 +8618,7 @@ public final Flowable delay(@NonNull FunctionThis version of {@code delay} operates by default on the {@code computation} {@link Scheduler}. * * - * @param delay + * @param time * the delay to shift the source by * @param unit * the {@link TimeUnit} in which {@code period} is defined @@ -8628,8 +8630,8 @@ public final Flowable delay(@NonNull Function delay(long delay, @NonNull TimeUnit unit) { - return delay(delay, unit, Schedulers.computation(), false); + public final Flowable delay(long time, @NonNull TimeUnit unit) { + return delay(time, unit, Schedulers.computation(), false); } /** @@ -8644,7 +8646,7 @@ public final Flowable delay(long delay, @NonNull TimeUnit unit) { *
This version of {@code delay} operates by default on the {@code computation} {@link Scheduler}.
* * - * @param delay + * @param time * the delay to shift the source by * @param unit * the {@link TimeUnit} in which {@code period} is defined @@ -8659,8 +8661,8 @@ public final Flowable delay(long delay, @NonNull TimeUnit unit) { @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Flowable delay(long delay, @NonNull TimeUnit unit, boolean delayError) { - return delay(delay, unit, Schedulers.computation(), delayError); + public final Flowable delay(long time, @NonNull TimeUnit unit, boolean delayError) { + return delay(time, unit, Schedulers.computation(), delayError); } /** @@ -8675,7 +8677,7 @@ public final Flowable delay(long delay, @NonNull TimeUnit unit, boolean delay *
You specify which {@link Scheduler} this operator will use.
* * - * @param delay + * @param time * the delay to shift the source by * @param unit * the time unit of {@code delay} @@ -8689,8 +8691,8 @@ public final Flowable delay(long delay, @NonNull TimeUnit unit, boolean delay @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Flowable delay(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { - return delay(delay, unit, scheduler, false); + public final Flowable delay(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + return delay(time, unit, scheduler, false); } /** @@ -8705,7 +8707,7 @@ public final Flowable delay(long delay, @NonNull TimeUnit unit, @NonNull Sche *
You specify which {@link Scheduler} this operator will use.
* * - * @param delay + * @param time * the delay to shift the source by * @param unit * the time unit of {@code delay} @@ -8722,11 +8724,11 @@ public final Flowable delay(long delay, @NonNull TimeUnit unit, @NonNull Sche @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Flowable delay(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean delayError) { + public final Flowable delay(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean delayError) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new FlowableDelay<>(this, Math.max(0L, delay), unit, scheduler, delayError)); + return RxJavaPlugins.onAssembly(new FlowableDelay<>(this, Math.max(0L, time), unit, scheduler, delayError)); } /** @@ -8807,7 +8809,7 @@ public final Flowable delaySubscription(@NonNull Publisher subscriptio *
This version of {@code delaySubscription} operates by default on the {@code computation} {@link Scheduler}.
* * - * @param delay + * @param time * the time to delay the subscription * @param unit * the time unit of {@code delay} @@ -8819,8 +8821,8 @@ public final Flowable delaySubscription(@NonNull Publisher subscriptio @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Flowable delaySubscription(long delay, @NonNull TimeUnit unit) { - return delaySubscription(delay, unit, Schedulers.computation()); + public final Flowable delaySubscription(long time, @NonNull TimeUnit unit) { + return delaySubscription(time, unit, Schedulers.computation()); } /** @@ -8835,7 +8837,7 @@ public final Flowable delaySubscription(long delay, @NonNull TimeUnit unit) { *
You specify which {@code Scheduler} this operator will use.
* * - * @param delay + * @param time * the time to delay the subscription * @param unit * the time unit of {@code delay} @@ -8849,8 +8851,8 @@ public final Flowable delaySubscription(long delay, @NonNull TimeUnit unit) { @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Flowable delaySubscription(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { - return delaySubscription(timer(delay, unit, scheduler)); + public final Flowable delaySubscription(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + return delaySubscription(timer(time, unit, scheduler)); } /** @@ -12334,20 +12336,20 @@ public final Flowable onBackpressureLatest() { *
{@code onErrorResumeNext} does not operate by default on a particular {@link Scheduler}.
* * - * @param resumeFunction + * @param fallbackSupplier * a function that returns a {@code Publisher} that will take over if the current {@code Flowable} encounters * an error * @return the new {@code Flowable} instance - * @throws NullPointerException if {@code resumeFunction} is {@code null} + * @throws NullPointerException if {@code fallbackSupplier} is {@code null} * @see ReactiveX operators documentation: Catch */ @CheckReturnValue @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable onErrorResumeNext(@NonNull Function> resumeFunction) { - Objects.requireNonNull(resumeFunction, "resumeFunction is null"); - return RxJavaPlugins.onAssembly(new FlowableOnErrorNext<>(this, resumeFunction)); + public final Flowable onErrorResumeNext(@NonNull Function> fallbackSupplier) { + Objects.requireNonNull(fallbackSupplier, "fallbackSupplier is null"); + return RxJavaPlugins.onAssembly(new FlowableOnErrorNext<>(this, fallbackSupplier)); } /** @@ -12379,20 +12381,20 @@ public final Flowable onErrorResumeNext(@NonNull Function{@code onErrorResumeWith} does not operate by default on a particular {@link Scheduler}. * * - * @param next + * @param fallback * the next {@code Publisher} source that will take over if the current {@code Flowable} encounters * an error * @return the new {@code Flowable} instance - * @throws NullPointerException if {@code next} is {@code null} + * @throws NullPointerException if {@code fallback} is {@code null} * @see ReactiveX operators documentation: Catch */ @CheckReturnValue @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable onErrorResumeWith(@NonNull Publisher<@NonNull ? extends T> next) { - Objects.requireNonNull(next, "next is null"); - return onErrorResumeNext(Functions.justFunction(next)); + public final Flowable onErrorResumeWith(@NonNull Publisher<@NonNull ? extends T> fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return onErrorResumeNext(Functions.justFunction(fallback)); } /** @@ -12420,20 +12422,20 @@ public final Flowable onErrorResumeWith(@NonNull Publisher<@NonNull ? extends *
{@code onErrorReturn} does not operate by default on a particular {@link Scheduler}.
* * - * @param valueSupplier + * @param itemSupplier * a function that returns a single value that will be emitted along with a regular {@code onComplete} in case * the current {@code Flowable} signals an {@code onError} event * @return the new {@code Flowable} instance - * @throws NullPointerException if {@code valueSupplier} is {@code null} + * @throws NullPointerException if {@code itemSupplier} is {@code null} * @see ReactiveX operators documentation: Catch */ @CheckReturnValue @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable onErrorReturn(@NonNull Function valueSupplier) { - Objects.requireNonNull(valueSupplier, "valueSupplier is null"); - return RxJavaPlugins.onAssembly(new FlowableOnErrorReturn<>(this, valueSupplier)); + public final Flowable onErrorReturn(@NonNull Function itemSupplier) { + Objects.requireNonNull(itemSupplier, "itemSupplier is null"); + return RxJavaPlugins.onAssembly(new FlowableOnErrorReturn<>(this, itemSupplier)); } /** @@ -16918,19 +16920,19 @@ public final Flowable timeout(@NonNull FunctionReactiveX operators documentation: Timeout */ @CheckReturnValue @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - public final Flowable timeout(@NonNull Function> itemTimeoutIndicator, @NonNull Publisher<@NonNull ? extends T> other) { - Objects.requireNonNull(other, "other is null"); - return timeout0(null, itemTimeoutIndicator, other); + public final Flowable timeout(@NonNull Function> itemTimeoutIndicator, @NonNull Publisher<@NonNull ? extends T> fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return timeout0(null, itemTimeoutIndicator, fallback); } /** @@ -16983,19 +16985,19 @@ public final Flowable timeout(long timeout, @NonNull TimeUnit unit) { * maximum duration between items before a timeout occurs * @param unit * the unit of time that applies to the {@code timeout} argument - * @param other + * @param fallback * the fallback {@code Publisher} to use in case of a timeout * @return the new {@code Flowable} instance - * @throws NullPointerException if {@code unit} or {@code other} is {@code null} + * @throws NullPointerException if {@code unit} or {@code fallback} is {@code null} * @see ReactiveX operators documentation: Timeout */ @CheckReturnValue @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.COMPUTATION) - public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Publisher<@NonNull ? extends T> other) { - Objects.requireNonNull(other, "other is null"); - return timeout0(timeout, unit, other, Schedulers.computation()); + public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Publisher<@NonNull ? extends T> fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return timeout0(timeout, unit, fallback, Schedulers.computation()); } /** @@ -17021,19 +17023,19 @@ public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull * the unit of time that applies to the {@code timeout} argument * @param scheduler * the {@code Scheduler} to run the timeout timers on - * @param other + * @param fallback * the {@code Publisher} to use as the fallback in case of a timeout * @return the new {@code Flowable} instance - * @throws NullPointerException if {@code unit}, {@code scheduler} or {@code other} is {@code null} + * @throws NullPointerException if {@code unit}, {@code scheduler} or {@code fallback} is {@code null} * @see ReactiveX operators documentation: Timeout */ @CheckReturnValue @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Publisher<@NonNull ? extends T> other) { - Objects.requireNonNull(other, "other is null"); - return timeout0(timeout, unit, other, scheduler); + public final Flowable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull Publisher<@NonNull ? extends T> fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return timeout0(timeout, unit, fallback, scheduler); } /** @@ -17136,10 +17138,10 @@ public final Flowable timeout(@NonNull Publisher firstTimeoutIndica * a function that returns a {@code Publisher} for each item emitted by the current {@code Flowable} and that * determines the timeout window in which the subsequent source item must arrive in order to * continue the sequence - * @param other + * @param fallback * the fallback {@code Publisher} to switch to if the current {@code Flowable} times out * @return the new {@code Flowable} instance - * @throws NullPointerException if {@code firstTimeoutIndicator}, {@code itemTimeoutIndicator} or {@code other} is {@code null} + * @throws NullPointerException if {@code firstTimeoutIndicator}, {@code itemTimeoutIndicator} or {@code fallback} is {@code null} * @see ReactiveX operators documentation: Timeout */ @CheckReturnValue @@ -17149,25 +17151,25 @@ public final Flowable timeout(@NonNull Publisher firstTimeoutIndica public final Flowable timeout( @NonNull Publisher firstTimeoutIndicator, @NonNull Function> itemTimeoutIndicator, - @NonNull Publisher<@NonNull ? extends T> other) { + @NonNull Publisher<@NonNull ? extends T> fallback) { Objects.requireNonNull(firstTimeoutIndicator, "firstTimeoutIndicator is null"); - Objects.requireNonNull(other, "other is null"); - return timeout0(firstTimeoutIndicator, itemTimeoutIndicator, other); + Objects.requireNonNull(fallback, "fallback is null"); + return timeout0(firstTimeoutIndicator, itemTimeoutIndicator, fallback); } - private Flowable timeout0(long timeout, TimeUnit unit, Publisher<@NonNull ? extends T> other, + private Flowable timeout0(long timeout, TimeUnit unit, Publisher<@NonNull ? extends T> fallback, Scheduler scheduler) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new FlowableTimeoutTimed<>(this, timeout, unit, scheduler, other)); + return RxJavaPlugins.onAssembly(new FlowableTimeoutTimed<>(this, timeout, unit, scheduler, fallback)); } private Flowable timeout0( Publisher firstTimeoutIndicator, Function> itemTimeoutIndicator, - Publisher<@NonNull ? extends T> other) { + Publisher<@NonNull ? extends T> fallback) { Objects.requireNonNull(itemTimeoutIndicator, "itemTimeoutIndicator is null"); - return RxJavaPlugins.onAssembly(new FlowableTimeout<>(this, firstTimeoutIndicator, itemTimeoutIndicator, other)); + return RxJavaPlugins.onAssembly(new FlowableTimeout<>(this, firstTimeoutIndicator, itemTimeoutIndicator, fallback)); } /** diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 82cb7545c2..4322afaa93 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -620,17 +620,17 @@ public static Maybe create(@NonNull MaybeOnSubscribe onSubscribe) { *
{@code defer} does not operate by default on a particular {@link Scheduler}.
* * @param the value type - * @param maybeSupplier the {@code Supplier} that is called for each individual {@code MaybeObserver} and + * @param supplier the {@code Supplier} that is called for each individual {@code MaybeObserver} and * returns a {@code MaybeSource} instance to subscribe to * @return the new {@code Maybe} instance - * @throws NullPointerException if {@code maybeSupplier} is {@code null} + * @throws NullPointerException if {@code supplier} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe defer(@NonNull Supplier> maybeSupplier) { - Objects.requireNonNull(maybeSupplier, "maybeSupplier is null"); - return RxJavaPlugins.onAssembly(new MaybeDefer<>(maybeSupplier)); + public static Maybe defer(@NonNull Supplier> supplier) { + Objects.requireNonNull(supplier, "supplier is null"); + return RxJavaPlugins.onAssembly(new MaybeDefer<>(supplier)); } /** @@ -663,20 +663,20 @@ public static Maybe empty() { *
{@code error} does not operate by default on a particular {@link Scheduler}.
* * - * @param error + * @param throwable * the particular {@link Throwable} to pass to {@link MaybeObserver#onError onError} * @param * the type of the item (ostensibly) emitted by the {@code Maybe} * @return the new {@code Maybe} instance - * @throws NullPointerException if {@code error} is {@code null} + * @throws NullPointerException if {@code throwable} is {@code null} * @see ReactiveX operators documentation: Throw */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe error(@NonNull Throwable error) { - Objects.requireNonNull(error, "error is null"); - return RxJavaPlugins.onAssembly(new MaybeError<>(error)); + public static Maybe error(@NonNull Throwable throwable) { + Objects.requireNonNull(throwable, "throwable is null"); + return RxJavaPlugins.onAssembly(new MaybeError<>(throwable)); } /** @@ -760,16 +760,16 @@ public static Maybe fromCompletable(@NonNull CompletableSource completabl *
{@code fromSingle} does not operate by default on a particular {@link Scheduler}.
* * @param the target type - * @param singleSource the {@code SingleSource} to convert from + * @param single the {@code SingleSource} to convert from * @return the new {@code Maybe} instance - * @throws NullPointerException if {@code singleSource} is {@code null} + * @throws NullPointerException if {@code single} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Maybe fromSingle(@NonNull SingleSource singleSource) { - Objects.requireNonNull(singleSource, "singleSource is null"); - return RxJavaPlugins.onAssembly(new MaybeFromSingle<>(singleSource)); + public static Maybe fromSingle(@NonNull SingleSource single) { + Objects.requireNonNull(single, "single is null"); + return RxJavaPlugins.onAssembly(new MaybeFromSingle<>(single)); } /** @@ -1799,9 +1799,10 @@ public static Maybe unsafeCreate(@NonNull MaybeSource onSubscribe) { * the factory function to create a resource object that depends on the {@code Maybe} * @param sourceSupplier * the factory function to create a {@code MaybeSource} - * @param resourceDisposer + * @param resourceCleanup * the function that will dispose of the resource * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} or {@code resourceCleanup} is {@code null} * @see ReactiveX operators documentation: Using */ @CheckReturnValue @@ -1809,8 +1810,8 @@ public static Maybe unsafeCreate(@NonNull MaybeSource onSubscribe) { @NonNull public static Maybe using(@NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, - @NonNull Consumer resourceDisposer) { - return using(resourceSupplier, sourceSupplier, resourceDisposer, true); + @NonNull Consumer resourceCleanup) { + return using(resourceSupplier, sourceSupplier, resourceCleanup, true); } /** @@ -1832,7 +1833,7 @@ public static Maybe using(@NonNull Supplier resourceSuppl * the factory function to create a resource object that depends on the {@code Maybe} * @param sourceSupplier * the factory function to create a {@code MaybeSource} - * @param resourceDisposer + * @param resourceCleanup * the function that will dispose of the resource * @param eager * If {@code true} then resource disposal will happen either on a {@code dispose()} call before the upstream is disposed @@ -1840,7 +1841,7 @@ public static Maybe using(@NonNull Supplier resourceSuppl * If {@code false} the resource disposal will happen either on a {@code dispose()} call after the upstream is disposed * or just after the emission of a terminal event ({@code onSuccess}, {@code onComplete} or {@code onError}). * @return the new {@code Maybe} instance - * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} or {@code resourceDisposer} is {@code null} + * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} or {@code resourceCleanup} is {@code null} * @see ReactiveX operators documentation: Using */ @CheckReturnValue @@ -1848,11 +1849,11 @@ public static Maybe using(@NonNull Supplier resourceSuppl @SchedulerSupport(SchedulerSupport.NONE) public static Maybe using(@NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, - @NonNull Consumer resourceDisposer, boolean eager) { + @NonNull Consumer resourceCleanup, boolean eager) { Objects.requireNonNull(resourceSupplier, "resourceSupplier is null"); Objects.requireNonNull(sourceSupplier, "sourceSupplier is null"); - Objects.requireNonNull(resourceDisposer, "resourceDisposer is null"); - return RxJavaPlugins.onAssembly(new MaybeUsing(resourceSupplier, sourceSupplier, resourceDisposer, eager)); + Objects.requireNonNull(resourceCleanup, "resourceCleanup is null"); + return RxJavaPlugins.onAssembly(new MaybeUsing(resourceSupplier, sourceSupplier, resourceCleanup, eager)); } /** @@ -2678,7 +2679,7 @@ public final Single defaultIfEmpty(@NonNull T defaultItem) { *
This version of {@code delay} operates by default on the {@code computation} {@link Scheduler}.
* * - * @param delay + * @param time * the delay to shift the source by * @param unit * the {@link TimeUnit} in which {@code period} is defined @@ -2690,8 +2691,8 @@ public final Single defaultIfEmpty(@NonNull T defaultItem) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Maybe delay(long delay, @NonNull TimeUnit unit) { - return delay(delay, unit, Schedulers.computation()); + public final Maybe delay(long time, @NonNull TimeUnit unit) { + return delay(time, unit, Schedulers.computation()); } /** @@ -2704,7 +2705,7 @@ public final Maybe delay(long delay, @NonNull TimeUnit unit) { *
you specify which {@code Scheduler} this operator will use.
* * - * @param delay + * @param time * the delay to shift the source by * @param unit * the time unit of {@code delay} @@ -2717,10 +2718,10 @@ public final Maybe delay(long delay, @NonNull TimeUnit unit) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Maybe delay(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + public final Maybe delay(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new MaybeDelay<>(this, Math.max(0L, delay), unit, scheduler)); + return RxJavaPlugins.onAssembly(new MaybeDelay<>(this, Math.max(0L, time), unit, scheduler)); } /** @@ -2789,7 +2790,7 @@ public final Maybe delaySubscription(@NonNull Publisher subscriptionIn *
This version of {@code delaySubscription} operates by default on the {@code computation} {@link Scheduler}.
* * - * @param delay + * @param time * the time to delay the subscription * @param unit * the time unit of {@code delay} @@ -2801,8 +2802,8 @@ public final Maybe delaySubscription(@NonNull Publisher subscriptionIn @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Maybe delaySubscription(long delay, @NonNull TimeUnit unit) { - return delaySubscription(delay, unit, Schedulers.computation()); + public final Maybe delaySubscription(long time, @NonNull TimeUnit unit) { + return delaySubscription(time, unit, Schedulers.computation()); } /** @@ -2815,7 +2816,7 @@ public final Maybe delaySubscription(long delay, @NonNull TimeUnit unit) { *
You specify which {@code Scheduler} this operator will use.
* * - * @param delay + * @param time * the time to delay the subscription * @param unit * the time unit of {@code delay} @@ -2828,8 +2829,8 @@ public final Maybe delaySubscription(long delay, @NonNull TimeUnit unit) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Maybe delaySubscription(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { - return delaySubscription(Flowable.timer(delay, unit, scheduler)); + public final Maybe delaySubscription(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + return delaySubscription(Flowable.timer(time, unit, scheduler)); } /** @@ -3198,21 +3199,21 @@ public final Maybe flatMap( * the type of items emitted by the resulting {@code Maybe} * @param mapper * a function that returns a {@code MaybeSource} for the item emitted by the current {@code Maybe} - * @param resultSelector + * @param combiner * a function that combines one item emitted by each of the source and collection {@code MaybeSource} and * returns an item to be emitted by the resulting {@code MaybeSource} * @return the new {@code Maybe} instance - * @throws NullPointerException if {@code mapper} or {@code resultSelector} is {@code null} + * @throws NullPointerException if {@code mapper} or {@code combiner} is {@code null} * @see ReactiveX operators documentation: FlatMap */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) public final Maybe flatMap(@NonNull Function> mapper, - @NonNull BiFunction resultSelector) { + @NonNull BiFunction combiner) { Objects.requireNonNull(mapper, "mapper is null"); - Objects.requireNonNull(resultSelector, "resultSelector is null"); - return RxJavaPlugins.onAssembly(new MaybeFlatMapBiSelector<>(this, mapper, resultSelector)); + Objects.requireNonNull(combiner, "combiner is null"); + return RxJavaPlugins.onAssembly(new MaybeFlatMapBiSelector<>(this, mapper, combiner)); } /** @@ -3880,19 +3881,19 @@ public final Maybe onErrorComplete(@NonNull Predicate pred *
{@code onErrorResumeWith} does not operate by default on a particular {@link Scheduler}.
* * - * @param next + * @param fallback * the next {@code MaybeSource} that will take over if the current {@code Maybe} encounters * an error * @return the new {@code Maybe} instance - * @throws NullPointerException if {@code next} is {@code null} + * @throws NullPointerException if {@code fallback} is {@code null} * @see ReactiveX operators documentation: Catch */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe onErrorResumeWith(@NonNull MaybeSource next) { - Objects.requireNonNull(next, "next is null"); - return onErrorResumeNext(Functions.justFunction(next)); + public final Maybe onErrorResumeWith(@NonNull MaybeSource fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return onErrorResumeNext(Functions.justFunction(fallback)); } /** @@ -3908,19 +3909,19 @@ public final Maybe onErrorResumeWith(@NonNull MaybeSource next) *
{@code onErrorResumeNext} does not operate by default on a particular {@link Scheduler}.
* * - * @param resumeFunction + * @param fallbackSupplier * a function that returns a {@code MaybeSource} that will take over if the current {@code Maybe} encounters * an error * @return the new {@code Maybe} instance - * @throws NullPointerException if {@code resumeFunction} is {@code null} + * @throws NullPointerException if {@code fallbackSupplier} is {@code null} * @see ReactiveX operators documentation: Catch */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe onErrorResumeNext(@NonNull Function> resumeFunction) { - Objects.requireNonNull(resumeFunction, "resumeFunction is null"); - return RxJavaPlugins.onAssembly(new MaybeOnErrorNext<>(this, resumeFunction)); + public final Maybe onErrorResumeNext(@NonNull Function> fallbackSupplier) { + Objects.requireNonNull(fallbackSupplier, "fallbackSupplier is null"); + return RxJavaPlugins.onAssembly(new MaybeOnErrorNext<>(this, fallbackSupplier)); } /** @@ -3936,19 +3937,19 @@ public final Maybe onErrorResumeNext(@NonNull Function{@code onErrorReturn} does not operate by default on a particular {@link Scheduler}. * * - * @param valueSupplier + * @param itemSupplier * a function that returns a single value that will be emitted as success value * the current {@code Maybe} signals an {@code onError} event * @return the new {@code Maybe} instance - * @throws NullPointerException if {@code valueSupplier} is {@code null} + * @throws NullPointerException if {@code itemSupplier} is {@code null} * @see ReactiveX operators documentation: Catch */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe onErrorReturn(@NonNull Function valueSupplier) { - Objects.requireNonNull(valueSupplier, "valueSupplier is null"); - return RxJavaPlugins.onAssembly(new MaybeOnErrorReturn<>(this, valueSupplier)); + public final Maybe onErrorReturn(@NonNull Function itemSupplier) { + Objects.requireNonNull(itemSupplier, "itemSupplier is null"); + return RxJavaPlugins.onAssembly(new MaybeOnErrorReturn<>(this, itemSupplier)); } /** diff --git a/src/main/java/io/reactivex/rxjava3/core/Observable.java b/src/main/java/io/reactivex/rxjava3/core/Observable.java index 0ea4c18b47..57456a9545 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Observable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Observable.java @@ -1692,20 +1692,20 @@ public static Observable empty() { *
{@code error} does not operate by default on a particular {@link Scheduler}.
* * - * @param errorSupplier + * @param supplier * a {@link Supplier} factory to return a {@link Throwable} for each individual {@code Observer} * @param * the type of the items (ostensibly) emitted by the {@code Observable} * @return the new {@code Observable} instance - * @throws NullPointerException if {@code errorSupplier} is {@code null} + * @throws NullPointerException if {@code supplier} is {@code null} * @see ReactiveX operators documentation: Throw */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable error(@NonNull Supplier errorSupplier) { - Objects.requireNonNull(errorSupplier, "errorSupplier is null"); - return RxJavaPlugins.onAssembly(new ObservableError<>(errorSupplier)); + public static Observable error(@NonNull Supplier supplier) { + Objects.requireNonNull(supplier, "supplier is null"); + return RxJavaPlugins.onAssembly(new ObservableError<>(supplier)); } /** @@ -1718,20 +1718,20 @@ public static Observable error(@NonNull Supplier err *
{@code error} does not operate by default on a particular {@link Scheduler}.
* * - * @param exception + * @param throwable * the particular {@link Throwable} to pass to {@link Observer#onError onError} * @param * the type of the items (ostensibly) emitted by the {@code Observable} * @return the new {@code Observable} instance - * @throws NullPointerException if {@code exception} is {@code null} + * @throws NullPointerException if {@code throwable} is {@code null} * @see ReactiveX operators documentation: Throw */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Observable error(@NonNull Throwable exception) { - Objects.requireNonNull(exception, "exception is null"); - return error(Functions.justSupplier(exception)); + public static Observable error(@NonNull Throwable throwable) { + Objects.requireNonNull(throwable, "throwable is null"); + return error(Functions.justSupplier(throwable)); } /** @@ -4082,9 +4082,10 @@ public static Observable unsafeCreate(@NonNull ObservableSource onSubs * the factory function to create a resource object that depends on the {@code ObservableSource} * @param sourceSupplier * the factory function to create an {@code ObservableSource} - * @param resourceDisposer + * @param resourceCleanup * the function that will dispose of the resource * @return the new {@code Observable} instance + * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} or {@code resourceCleanup} is {@code null} * @see ReactiveX operators documentation: Using */ @CheckReturnValue @@ -4093,8 +4094,8 @@ public static Observable unsafeCreate(@NonNull ObservableSource onSubs public static Observable using( @NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, - @NonNull Consumer resourceDisposer) { - return using(resourceSupplier, sourceSupplier, resourceDisposer, true); + @NonNull Consumer resourceCleanup) { + return using(resourceSupplier, sourceSupplier, resourceCleanup, true); } /** @@ -4114,7 +4115,7 @@ public static Observable using( * the factory function to create a resource object that depends on the {@code ObservableSource} * @param sourceSupplier * the factory function to create an {@code ObservableSource} - * @param resourceDisposer + * @param resourceCleanup * the function that will dispose of the resource * @param eager * If {@code true}, the resource disposal will happen either on a {@code dispose()} call before the upstream is disposed @@ -4122,7 +4123,7 @@ public static Observable using( * If {@code false}, the resource disposal will happen either on a {@code dispose()} call after the upstream is disposed * or just after the emission of a terminal event ({@code onComplete} or {@code onError}). * @return the new {@code Observable} instance - * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} and {@code resourceDisposer} is {@code null} + * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} and {@code resourceCleanup} is {@code null} * @see ReactiveX operators documentation: Using * @since 2.0 */ @@ -4132,11 +4133,11 @@ public static Observable using( public static Observable using( @NonNull Supplier resourceSupplier, @NonNull Function> sourceSupplier, - @NonNull Consumer resourceDisposer, boolean eager) { + @NonNull Consumer resourceCleanup, boolean eager) { Objects.requireNonNull(resourceSupplier, "resourceSupplier is null"); Objects.requireNonNull(sourceSupplier, "sourceSupplier is null"); - Objects.requireNonNull(resourceDisposer, "resourceDisposer is null"); - return RxJavaPlugins.onAssembly(new ObservableUsing(resourceSupplier, sourceSupplier, resourceDisposer, eager)); + Objects.requireNonNull(resourceCleanup, "resourceCleanup is null"); + return RxJavaPlugins.onAssembly(new ObservableUsing(resourceSupplier, sourceSupplier, resourceCleanup, eager)); } /** @@ -5428,17 +5429,19 @@ public final Iterable blockingLatest() { *
{@code blockingMostRecent} does not operate by default on a particular {@link Scheduler}.
* * - * @param initialValue + * @param initialItem * the initial value that the {@code Iterable} sequence will yield if the current * {@code Observable} has not yet emitted an item * @return the new {@code Iterable} instance + * @throws NullPointerException if {@code initialItem} is {@code null} * @see ReactiveX documentation: First */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Iterable blockingMostRecent(@NonNull T initialValue) { - return new BlockingObservableMostRecent<>(this, initialValue); + public final Iterable blockingMostRecent(@NonNull T initialItem) { + Objects.requireNonNull(initialItem, "initialItem is null"); + return new BlockingObservableMostRecent<>(this, initialItem); } /** @@ -6236,23 +6239,23 @@ public final > Observable buffer(int count, i * @param the collection subclass type to buffer into * @param * the boundary value type (ignored) - * @param boundary + * @param boundaryIndicator * the boundary {@code ObservableSource} * @param bufferSupplier * a factory function that returns an instance of the collection subclass to be used and returned * as the buffer * @return the new {@code Observable} instance - * @throws NullPointerException if {@code boundary} or {@code bufferSupplier} is {@code null} + * @throws NullPointerException if {@code boundaryIndicator} or {@code bufferSupplier} is {@code null} * @see #buffer(ObservableSource, int) * @see ReactiveX operators documentation: Buffer */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final > Observable buffer(@NonNull ObservableSource boundary, @NonNull Supplier bufferSupplier) { - Objects.requireNonNull(boundary, "boundary is null"); + public final > Observable buffer(@NonNull ObservableSource boundaryIndicator, @NonNull Supplier bufferSupplier) { + Objects.requireNonNull(boundaryIndicator, "boundaryIndicator is null"); Objects.requireNonNull(bufferSupplier, "bufferSupplier is null"); - return RxJavaPlugins.onAssembly(new ObservableBufferExactBoundary<>(this, boundary, bufferSupplier)); + return RxJavaPlugins.onAssembly(new ObservableBufferExactBoundary<>(this, boundaryIndicator, bufferSupplier)); } /** @@ -6416,22 +6419,22 @@ public final Observable cast(@NonNull Class clazz) { * * * @param the accumulator and output type - * @param initialValueSupplier + * @param initialItemSupplier * the mutable data structure that will collect the items * @param collector * a function that accepts the {@code state} and an emitted item, and modifies the accumulator accordingly * accordingly * @return the new {@code Single} instance - * @throws NullPointerException if {@code initialValueSupplier} or {@code collector} is {@code null} + * @throws NullPointerException if {@code initialItemSupplier} or {@code collector} is {@code null} * @see ReactiveX operators documentation: Reduce */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single collect(@NonNull Supplier initialValueSupplier, @NonNull BiConsumer collector) { - Objects.requireNonNull(initialValueSupplier, "initialValueSupplier is null"); + public final Single collect(@NonNull Supplier initialItemSupplier, @NonNull BiConsumer collector) { + Objects.requireNonNull(initialItemSupplier, "initialItemSupplier is null"); Objects.requireNonNull(collector, "collector is null"); - return RxJavaPlugins.onAssembly(new ObservableCollectSingle<>(this, initialValueSupplier, collector)); + return RxJavaPlugins.onAssembly(new ObservableCollectSingle<>(this, initialItemSupplier, collector)); } /** @@ -6451,21 +6454,21 @@ public final Single collect(@NonNull Supplier initialValueSu * * * @param the accumulator and output type - * @param initialValue + * @param initialItem * the mutable data structure that will collect the items * @param collector * a function that accepts the {@code state} and an emitted item, and modifies the accumulator accordingly * accordingly * @return the new {@code Single} instance - * @throws NullPointerException if {@code initialValue} or {@code collector} is {@code null} + * @throws NullPointerException if {@code initialItem} or {@code collector} is {@code null} * @see ReactiveX operators documentation: Reduce */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single collectInto(@NonNull U initialValue, @NonNull BiConsumer collector) { - Objects.requireNonNull(initialValue, "initialValue is null"); - return collect(Functions.justSupplier(initialValue), collector); + public final Single collectInto(@NonNull U initialItem, @NonNull BiConsumer collector) { + Objects.requireNonNull(initialItem, "initialItem is null"); + return collect(Functions.justSupplier(initialItem), collector); } /** @@ -7454,18 +7457,18 @@ public final Observable concatWith(@NonNull CompletableSource other) { *
{@code contains} does not operate by default on a particular {@link Scheduler}.
* * - * @param element + * @param item * the item to search for in the emissions from the current {@code Observable} * @return the new {@code Single} instance - * @throws NullPointerException if {@code element} is {@code null} + * @throws NullPointerException if {@code item} is {@code null} * @see ReactiveX operators documentation: Contains */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single contains(@NonNull Object element) { - Objects.requireNonNull(element, "element is null"); - return any(Functions.equalsWith(element)); + public final Single contains(@NonNull Object item) { + Objects.requireNonNull(item, "item is null"); + return any(Functions.equalsWith(item)); } /** @@ -7509,18 +7512,18 @@ public final Single count() { * * @param * the debounce value type (ignored) - * @param debounceSelector + * @param debounceIndicator * function to return a sequence that indicates the throttle duration for each item via its own emission or completion * @return the new {@code Observable} instance - * @throws NullPointerException if {@code debounceSelector} is {@code null} + * @throws NullPointerException if {@code debounceIndicator} is {@code null} * @see ReactiveX operators documentation: Debounce */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable debounce(@NonNull Function> debounceSelector) { - Objects.requireNonNull(debounceSelector, "debounceSelector is null"); - return RxJavaPlugins.onAssembly(new ObservableDebounce<>(this, debounceSelector)); + public final Observable debounce(@NonNull Function> debounceIndicator) { + Objects.requireNonNull(debounceIndicator, "debounceIndicator is null"); + return RxJavaPlugins.onAssembly(new ObservableDebounce<>(this, debounceIndicator)); } /** @@ -7644,20 +7647,20 @@ public final Observable defaultIfEmpty(@NonNull T defaultItem) { * * @param * the item delay value type (ignored) - * @param itemDelay + * @param itemDelayIndicator * a function that returns an {@code ObservableSource} for each item emitted by the current {@code Observable}, which is * then used to delay the emission of that item by the resulting {@code Observable} until the {@code ObservableSource} * returned from {@code itemDelay} emits an item * @return the new {@code Observable} instance - * @throws NullPointerException if {@code itemDelay} is {@code null} + * @throws NullPointerException if {@code itemDelayIndicator} is {@code null} * @see ReactiveX operators documentation: Delay */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable delay(@NonNull Function> itemDelay) { - Objects.requireNonNull(itemDelay, "itemDelay is null"); - return flatMap(ObservableInternalHelper.itemDelay(itemDelay)); + public final Observable delay(@NonNull Function> itemDelayIndicator) { + Objects.requireNonNull(itemDelayIndicator, "itemDelayIndicator is null"); + return flatMap(ObservableInternalHelper.itemDelay(itemDelayIndicator)); } /** @@ -7670,7 +7673,7 @@ public final Observable delay(@NonNull FunctionThis version of {@code delay} operates by default on the {@code computation} {@link Scheduler}. * * - * @param delay + * @param time * the delay to shift the source by * @param unit * the {@link TimeUnit} in which {@code period} is defined @@ -7683,8 +7686,8 @@ public final Observable delay(@NonNull Function delay(long delay, @NonNull TimeUnit unit) { - return delay(delay, unit, Schedulers.computation(), false); + public final Observable delay(long time, @NonNull TimeUnit unit) { + return delay(time, unit, Schedulers.computation(), false); } /** @@ -7697,7 +7700,7 @@ public final Observable delay(long delay, @NonNull TimeUnit unit) { *
This version of {@code delay} operates by default on the {@code computation} {@link Scheduler}.
* * - * @param delay + * @param time * the delay to shift the source by * @param unit * the {@link TimeUnit} in which {@code period} is defined @@ -7712,8 +7715,8 @@ public final Observable delay(long delay, @NonNull TimeUnit unit) { @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Observable delay(long delay, @NonNull TimeUnit unit, boolean delayError) { - return delay(delay, unit, Schedulers.computation(), delayError); + public final Observable delay(long time, @NonNull TimeUnit unit, boolean delayError) { + return delay(time, unit, Schedulers.computation(), delayError); } /** @@ -7726,7 +7729,7 @@ public final Observable delay(long delay, @NonNull TimeUnit unit, boolean del *
You specify which {@link Scheduler} this operator will use.
* * - * @param delay + * @param time * the delay to shift the source by * @param unit * the time unit of {@code delay} @@ -7739,8 +7742,8 @@ public final Observable delay(long delay, @NonNull TimeUnit unit, boolean del @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Observable delay(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { - return delay(delay, unit, scheduler, false); + public final Observable delay(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + return delay(time, unit, scheduler, false); } /** @@ -7753,7 +7756,7 @@ public final Observable delay(long delay, @NonNull TimeUnit unit, @NonNull Sc *
You specify which {@link Scheduler} this operator will use.
* * - * @param delay + * @param time * the delay to shift the source by * @param unit * the time unit of {@code delay} @@ -7769,11 +7772,11 @@ public final Observable delay(long delay, @NonNull TimeUnit unit, @NonNull Sc @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Observable delay(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean delayError) { + public final Observable delay(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean delayError) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new ObservableDelay<>(this, delay, unit, scheduler, delayError)); + return RxJavaPlugins.onAssembly(new ObservableDelay<>(this, time, unit, scheduler, delayError)); } /** @@ -7793,23 +7796,23 @@ public final Observable delay(long delay, @NonNull TimeUnit unit, @NonNull Sc * the subscription delay value type (ignored) * @param * the item delay value type (ignored) - * @param subscriptionDelay + * @param subscriptionIndicator * a function that returns an {@code ObservableSource} that triggers the subscription to the current {@code Observable} * once it emits any item - * @param itemDelay + * @param itemDelayIndicator * a function that returns an {@code ObservableSource} for each item emitted by the current {@code Observable}, which is * then used to delay the emission of that item by the resulting {@code Observable} until the {@code ObservableSource} * returned from {@code itemDelay} emits an item * @return the new {@code Observable} instance - * @throws NullPointerException if {@code subscriptionDelay} or {@code itemDelay} is {@code null} + * @throws NullPointerException if {@code subscriptionIndicator} or {@code itemDelayIndicator} is {@code null} * @see ReactiveX operators documentation: Delay */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable delay(@NonNull ObservableSource subscriptionDelay, - @NonNull Function> itemDelay) { - return delaySubscription(subscriptionDelay).delay(itemDelay); + public final Observable delay(@NonNull ObservableSource subscriptionIndicator, + @NonNull Function> itemDelayIndicator) { + return delaySubscription(subscriptionIndicator).delay(itemDelayIndicator); } /** @@ -7823,18 +7826,18 @@ public final Observable delay(@NonNull ObservableSource subscriptio * * * @param the value type of the other {@code Observable}, irrelevant - * @param other the other {@code ObservableSource} that should trigger the subscription + * @param subscriptionIndicator the other {@code ObservableSource} that should trigger the subscription * to the current {@code Observable}. * @return the new {@code Observable} instance - * @throws NullPointerException if {@code other} is {@code null} + * @throws NullPointerException if {@code subscriptionIndicator} is {@code null} * @since 2.0 */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable delaySubscription(@NonNull ObservableSource other) { - Objects.requireNonNull(other, "other is null"); - return RxJavaPlugins.onAssembly(new ObservableDelaySubscriptionOther<>(this, other)); + public final Observable delaySubscription(@NonNull ObservableSource subscriptionIndicator) { + Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); + return RxJavaPlugins.onAssembly(new ObservableDelaySubscriptionOther<>(this, subscriptionIndicator)); } /** @@ -7846,7 +7849,7 @@ public final Observable delaySubscription(@NonNull ObservableSource ot *
This version of {@code delaySubscription} operates by default on the {@code computation} {@link Scheduler}.
* * - * @param delay + * @param time * the time to delay the subscription * @param unit * the time unit of {@code delay} @@ -7857,8 +7860,8 @@ public final Observable delaySubscription(@NonNull ObservableSource ot @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Observable delaySubscription(long delay, @NonNull TimeUnit unit) { - return delaySubscription(delay, unit, Schedulers.computation()); + public final Observable delaySubscription(long time, @NonNull TimeUnit unit) { + return delaySubscription(time, unit, Schedulers.computation()); } /** @@ -7871,7 +7874,7 @@ public final Observable delaySubscription(long delay, @NonNull TimeUnit unit) *
You specify which {@code Scheduler} this operator will use.
* * - * @param delay + * @param time * the time to delay the subscription * @param unit * the time unit of {@code delay} @@ -7884,8 +7887,8 @@ public final Observable delaySubscription(long delay, @NonNull TimeUnit unit) @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Observable delaySubscription(long delay, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { - return delaySubscription(timer(delay, unit, scheduler)); + public final Observable delaySubscription(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + return delaySubscription(timer(time, unit, scheduler)); } /** @@ -10366,19 +10369,19 @@ public final Observable ofType(@NonNull Class clazz) { *
{@code onErrorResumeNext} does not operate by default on a particular {@link Scheduler}.
* * - * @param resumeFunction + * @param fallbackSupplier * a function that returns an {@code ObservableSource} that will take over if the current {@code Observable} encounters * an error * @return the new {@code Observable} instance - * @throws NullPointerException if {@code resumeFunction} is {@code null} + * @throws NullPointerException if {@code fallbackSupplier} is {@code null} * @see ReactiveX operators documentation: Catch */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable onErrorResumeNext(@NonNull Function> resumeFunction) { - Objects.requireNonNull(resumeFunction, "resumeFunction is null"); - return RxJavaPlugins.onAssembly(new ObservableOnErrorNext<>(this, resumeFunction)); + public final Observable onErrorResumeNext(@NonNull Function> fallbackSupplier) { + Objects.requireNonNull(fallbackSupplier, "fallbackSupplier is null"); + return RxJavaPlugins.onAssembly(new ObservableOnErrorNext<>(this, fallbackSupplier)); } /** @@ -10404,19 +10407,19 @@ public final Observable onErrorResumeNext(@NonNull Function{@code onErrorResumeWith} does not operate by default on a particular {@link Scheduler}. * * - * @param next + * @param fallback * the next {@code ObservableSource} source that will take over if the current {@code Observable} encounters * an error * @return the new {@code Observable} instance - * @throws NullPointerException if {@code next} is {@code null} + * @throws NullPointerException if {@code fallback} is {@code null} * @see ReactiveX operators documentation: Catch */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable onErrorResumeWith(@NonNull ObservableSource next) { - Objects.requireNonNull(next, "next is null"); - return onErrorResumeNext(Functions.justFunction(next)); + public final Observable onErrorResumeWith(@NonNull ObservableSource fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return onErrorResumeNext(Functions.justFunction(fallback)); } /** @@ -10439,19 +10442,19 @@ public final Observable onErrorResumeWith(@NonNull ObservableSource{@code onErrorReturn} does not operate by default on a particular {@link Scheduler}. * * - * @param valueSupplier + * @param itemSupplier * a function that returns a single value that will be emitted along with a regular {@code onComplete} in case * the current {@code Observable} signals an {@code onError} event * @return the new {@code Observable} instance - * @throws NullPointerException if {@code valueSupplier} is {@code null} + * @throws NullPointerException if {@code itemSupplier} is {@code null} * @see ReactiveX operators documentation: Catch */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable onErrorReturn(@NonNull Function valueSupplier) { - Objects.requireNonNull(valueSupplier, "valueSupplier is null"); - return RxJavaPlugins.onAssembly(new ObservableOnErrorReturn<>(this, valueSupplier)); + public final Observable onErrorReturn(@NonNull Function itemSupplier) { + Objects.requireNonNull(itemSupplier, "itemSupplier is null"); + return RxJavaPlugins.onAssembly(new ObservableOnErrorReturn<>(this, itemSupplier)); } /** @@ -12488,18 +12491,18 @@ public final Observable sorted() { *
{@code sorted} does not operate by default on a particular {@link Scheduler}.
* * - * @param sortFunction + * @param comparator * a function that compares two items emitted by the current {@code Observable} and returns an {@code int} * that indicates their sort order - * @throws NullPointerException if {@code sortFunction} is {@code null} + * @throws NullPointerException if {@code comparator} is {@code null} * @return the new {@code Observable} instance */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable sorted(@NonNull Comparator sortFunction) { - Objects.requireNonNull(sortFunction, "sortFunction is null"); - return toList().toObservable().map(Functions.listSorter(sortFunction)).flatMapIterable(Functions.identity()); + public final Observable sorted(@NonNull Comparator comparator) { + Objects.requireNonNull(comparator, "comparator is null"); + return toList().toObservable().map(Functions.listSorter(comparator)).flatMapIterable(Functions.identity()); } /** @@ -14130,19 +14133,19 @@ public final Observable timeout(@NonNull FunctionReactiveX operators documentation: Timeout */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull public final Observable timeout(@NonNull Function> itemTimeoutIndicator, - @NonNull ObservableSource other) { - Objects.requireNonNull(other, "other is null"); - return timeout0(null, itemTimeoutIndicator, other); + @NonNull ObservableSource fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return timeout0(null, itemTimeoutIndicator, fallback); } /** @@ -14187,18 +14190,18 @@ public final Observable timeout(long timeout, @NonNull TimeUnit unit) { * maximum duration between items before a timeout occurs * @param unit * the unit of time that applies to the {@code timeout} argument - * @param other + * @param fallback * the fallback {@code ObservableSource} to use in case of a timeout * @return the new {@code Observable} instance - * @throws NullPointerException if {@code unit} or {@code other} is {@code null} + * @throws NullPointerException if {@code unit} or {@code fallback} is {@code null} * @see ReactiveX operators documentation: Timeout */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull - public final Observable timeout(long timeout, @NonNull TimeUnit unit, @NonNull ObservableSource other) { - Objects.requireNonNull(other, "other is null"); - return timeout0(timeout, unit, other, Schedulers.computation()); + public final Observable timeout(long timeout, @NonNull TimeUnit unit, @NonNull ObservableSource fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return timeout0(timeout, unit, fallback, Schedulers.computation()); } /** @@ -14219,18 +14222,18 @@ public final Observable timeout(long timeout, @NonNull TimeUnit unit, @NonNul * the unit of time that applies to the {@code timeout} argument * @param scheduler * the {@code Scheduler} to run the timeout timers on - * @param other + * @param fallback * the {@code ObservableSource} to use as the fallback in case of a timeout * @return the new {@code Observable} instance - * @throws NullPointerException if {@code unit}, {@code scheduler} or {@code other} is {@code null} + * @throws NullPointerException if {@code unit}, {@code scheduler} or {@code fallback} is {@code null} * @see ReactiveX operators documentation: Timeout */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) @NonNull - public final Observable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull ObservableSource other) { - Objects.requireNonNull(other, "other is null"); - return timeout0(timeout, unit, other, scheduler); + public final Observable timeout(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, @NonNull ObservableSource fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return timeout0(timeout, unit, fallback, scheduler); } /** @@ -14319,11 +14322,11 @@ public final Observable timeout(@NonNull ObservableSource firstTime * a function that returns an {@code ObservableSource} for each item emitted by the current {@code Observable} and that * determines the timeout window in which the subsequent source item must arrive in order to * continue the sequence - * @param other + * @param fallback * the fallback {@code ObservableSource} to switch to if the current {@code Observable} times out * @return the new {@code Observable} instance * @throws NullPointerException - * if {@code firstTimeoutIndicator}, {@code itemTimeoutIndicator} or {@code other} is {@code null} + * if {@code firstTimeoutIndicator}, {@code itemTimeoutIndicator} or {@code fallback} is {@code null} * @see ReactiveX operators documentation: Timeout */ @CheckReturnValue @@ -14332,28 +14335,28 @@ public final Observable timeout(@NonNull ObservableSource firstTime public final Observable timeout( @NonNull ObservableSource firstTimeoutIndicator, @NonNull Function> itemTimeoutIndicator, - @NonNull ObservableSource other) { + @NonNull ObservableSource fallback) { Objects.requireNonNull(firstTimeoutIndicator, "firstTimeoutIndicator is null"); - Objects.requireNonNull(other, "other is null"); - return timeout0(firstTimeoutIndicator, itemTimeoutIndicator, other); + Objects.requireNonNull(fallback, "fallback is null"); + return timeout0(firstTimeoutIndicator, itemTimeoutIndicator, fallback); } @NonNull private Observable timeout0(long timeout, @NonNull TimeUnit unit, - @Nullable ObservableSource other, + @Nullable ObservableSource fallback, @NonNull Scheduler scheduler) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new ObservableTimeoutTimed<>(this, timeout, unit, scheduler, other)); + return RxJavaPlugins.onAssembly(new ObservableTimeoutTimed<>(this, timeout, unit, scheduler, fallback)); } @NonNull private Observable timeout0( @NonNull ObservableSource firstTimeoutIndicator, @NonNull Function> itemTimeoutIndicator, - @Nullable ObservableSource other) { + @Nullable ObservableSource fallback) { Objects.requireNonNull(itemTimeoutIndicator, "itemTimeoutIndicator is null"); - return RxJavaPlugins.onAssembly(new ObservableTimeout<>(this, firstTimeoutIndicator, itemTimeoutIndicator, other)); + return RxJavaPlugins.onAssembly(new ObservableTimeout<>(this, firstTimeoutIndicator, itemTimeoutIndicator, fallback)); } /** @@ -15538,17 +15541,17 @@ public final Observable> window( * * @param * the window element type (ignored) - * @param boundary + * @param boundaryIndicator * an {@code ObservableSource} whose emitted items close and open windows * @return the new {@code Observable} instance - * @throws NullPointerException if {@code boundary} is {@code null} + * @throws NullPointerException if {@code boundaryIndicator} is {@code null} * @see ReactiveX operators documentation: Window */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable> window(@NonNull ObservableSource boundary) { - return window(boundary, bufferSize()); + public final Observable> window(@NonNull ObservableSource boundaryIndicator) { + return window(boundaryIndicator, bufferSize()); } /** @@ -15569,22 +15572,22 @@ public final Observable> window(@NonNull ObservableSource b * * @param * the window element type (ignored) - * @param boundary + * @param boundaryIndicator * an {@code ObservableSource} whose emitted items close and open windows * @param bufferSize * the capacity hint for the buffer in the inner windows * @return the new {@code Observable} instance - * @throws NullPointerException if {@code boundary} is {@code null} + * @throws NullPointerException if {@code boundaryIndicator} is {@code null} * @throws IllegalArgumentException if {@code bufferSize} is non-positive * @see ReactiveX operators documentation: Window */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Observable> window(@NonNull ObservableSource boundary, int bufferSize) { - Objects.requireNonNull(boundary, "boundary is null"); + public final Observable> window(@NonNull ObservableSource boundaryIndicator, int bufferSize) { + Objects.requireNonNull(boundaryIndicator, "boundaryIndicator is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); - return RxJavaPlugins.onAssembly(new ObservableWindowBoundary<>(this, boundary, bufferSize)); + return RxJavaPlugins.onAssembly(new ObservableWindowBoundary<>(this, boundaryIndicator, bufferSize)); } /** diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index eb90b83fcb..0541ce8657 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -557,17 +557,17 @@ public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends S *
{@code defer} does not operate by default on a particular {@link Scheduler}.
* * @param the value type - * @param singleSupplier the {@code Supplier} that is called for each individual {@code SingleObserver} and + * @param supplier the {@code Supplier} that is called for each individual {@code SingleObserver} and * returns a {@code SingleSource} instance to subscribe to - * @throws NullPointerException if {@code singleSupplier} is {@code null} + * @throws NullPointerException if {@code supplier} is {@code null} * @return the new {@code Single} instance */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single defer(@NonNull Supplier> singleSupplier) { - Objects.requireNonNull(singleSupplier, "singleSupplier is null"); - return RxJavaPlugins.onAssembly(new SingleDefer<>(singleSupplier)); + public static Single defer(@NonNull Supplier> supplier) { + Objects.requireNonNull(supplier, "supplier is null"); + return RxJavaPlugins.onAssembly(new SingleDefer<>(supplier)); } /** @@ -579,17 +579,17 @@ public static Single defer(@NonNull Supplier{@code error} does not operate by default on a particular {@link Scheduler}. * * @param the value type - * @param errorSupplier the {@link Supplier} that is called for each individual {@code SingleObserver} and + * @param supplier the {@link Supplier} that is called for each individual {@code SingleObserver} and * returns a {@code Throwable} instance to be emitted. - * @throws NullPointerException if {@code errorSupplier} is {@code null} + * @throws NullPointerException if {@code supplier} is {@code null} * @return the new {@code Single} instance */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single error(@NonNull Supplier errorSupplier) { - Objects.requireNonNull(errorSupplier, "errorSupplier is null"); - return RxJavaPlugins.onAssembly(new SingleError<>(errorSupplier)); + public static Single error(@NonNull Supplier supplier) { + Objects.requireNonNull(supplier, "supplier is null"); + return RxJavaPlugins.onAssembly(new SingleError<>(supplier)); } /** @@ -602,21 +602,21 @@ public static Single error(@NonNull Supplier errorSu *
{@code error} does not operate by default on a particular {@link Scheduler}.
* * - * @param exception + * @param throwable * the particular {@link Throwable} to pass to {@link SingleObserver#onError onError} * @param * the type of the item (ostensibly) emitted by the {@code Single} * @return the new {@code Single} that invokes the subscriber's {@link SingleObserver#onError onError} method when * the subscriber subscribes to it - * @throws NullPointerException if {@code exception} is {@code null} + * @throws NullPointerException if {@code throwable} is {@code null} * @see ReactiveX operators documentation: Throw */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single error(@NonNull Throwable exception) { - Objects.requireNonNull(exception, "exception is null"); - return error(Functions.justSupplier(exception)); + public static Single error(@NonNull Throwable throwable) { + Objects.requireNonNull(throwable, "throwable is null"); + return error(Functions.justSupplier(throwable)); } /** @@ -782,18 +782,18 @@ public static Single fromPublisher(@NonNull Publisher<@NonNull ? extends *
{@code fromObservable} does not operate by default on a particular {@link Scheduler}.
* * - * @param observableSource the source sequence to wrap, not {@code null} + * @param observable the source sequence to wrap, not {@code null} * @param * the type of the item emitted by the {@code Single}. * @return the new {@code Single} instance - * @throws NullPointerException if {@code observableSource} is {@code null} + * @throws NullPointerException if {@code observable} is {@code null} */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single fromObservable(@NonNull ObservableSource observableSource) { - Objects.requireNonNull(observableSource, "observableSource is null"); - return RxJavaPlugins.onAssembly(new ObservableSingleSingle<>(observableSource, null)); + public static Single fromObservable(@NonNull ObservableSource observable) { + Objects.requireNonNull(observable, "observable is null"); + return RxJavaPlugins.onAssembly(new ObservableSingleSingle<>(observable, null)); } /** @@ -1446,22 +1446,23 @@ public static Single unsafeCreate(@NonNull SingleSource onSubscribe) { * @param the value type of the {@code SingleSource} generated * @param the resource type * @param resourceSupplier the {@link Supplier} called for each {@link SingleObserver} to generate a resource object - * @param singleFunction the function called with the returned resource + * @param sourceSupplier the function called with the returned resource * object from {@code resourceSupplier} and should return a {@code SingleSource} instance * to be run by the operator - * @param disposer the consumer of the generated resource that is called exactly once for + * @param resourceCleanup the consumer of the generated resource that is called exactly once for * that particular resource when the generated {@code SingleSource} terminates * (successfully or with an error) or gets disposed. * @return the new {@code Single} instance + * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} and {@code resourceCleanup} is {@code null} * @since 2.0 */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull public static Single using(@NonNull Supplier resourceSupplier, - @NonNull Function> singleFunction, - @NonNull Consumer disposer) { - return using(resourceSupplier, singleFunction, disposer, true); + @NonNull Function> sourceSupplier, + @NonNull Consumer resourceCleanup) { + return using(resourceSupplier, sourceSupplier, resourceCleanup, true); } /** @@ -1476,10 +1477,10 @@ public static Single using(@NonNull Supplier resourceSupplier, * @param the value type of the {@code SingleSource} generated * @param the resource type * @param resourceSupplier the {@link Supplier} called for each {@link SingleObserver} to generate a resource object - * @param singleFunction the function called with the returned resource + * @param sourceSupplier the function called with the returned resource * object from {@code resourceSupplier} and should return a {@code SingleSource} instance * to be run by the operator - * @param disposer the consumer of the generated resource that is called exactly once for + * @param resourceCleanup the consumer of the generated resource that is called exactly once for * that particular resource when the generated {@code SingleSource} terminates * (successfully or with an error) or gets disposed. * @param eager @@ -1488,7 +1489,7 @@ public static Single using(@NonNull Supplier resourceSupplier, * If {@code false} the resource disposal will happen either on a {@code dispose()} call after the upstream is disposed * or just after the emission of a terminal event ({@code onSuccess} or {@code onError}). * @return the new {@code Single} instance - * @throws NullPointerException if {@code resourceSupplier}, {@code singleFunction} or {@code disposer} is {@code null} + * @throws NullPointerException if {@code resourceSupplier}, {@code sourceSupplier} or {@code resourceCleanup} is {@code null} * @since 2.0 */ @CheckReturnValue @@ -1496,14 +1497,14 @@ public static Single using(@NonNull Supplier resourceSupplier, @SchedulerSupport(SchedulerSupport.NONE) public static Single using( @NonNull Supplier resourceSupplier, - @NonNull Function> singleFunction, - @NonNull Consumer disposer, + @NonNull Function> sourceSupplier, + @NonNull Consumer resourceCleanup, boolean eager) { Objects.requireNonNull(resourceSupplier, "resourceSupplier is null"); - Objects.requireNonNull(singleFunction, "singleFunction is null"); - Objects.requireNonNull(disposer, "disposer is null"); + Objects.requireNonNull(sourceSupplier, "sourceSupplier is null"); + Objects.requireNonNull(resourceCleanup, "resourceCleanup is null"); - return RxJavaPlugins.onAssembly(new SingleUsing<>(resourceSupplier, singleFunction, disposer, eager)); + return RxJavaPlugins.onAssembly(new SingleUsing<>(resourceSupplier, sourceSupplier, resourceCleanup, eager)); } /** @@ -2297,18 +2298,18 @@ public final Single delay(long time, @NonNull TimeUnit unit, @NonNull Schedul *
Scheduler:
*
{@code delaySubscription} does not operate by default on a particular {@link Scheduler}.
* - * @param other the {@code CompletableSource} that has to complete before the subscription to the + * @param subscriptionIndicator the {@code CompletableSource} that has to complete before the subscription to the * current {@code Single} happens * @return the new {@code Single} instance - * @throws NullPointerException if {@code other} is {@code null} + * @throws NullPointerException if {@code subscriptionIndicator} is {@code null} * @since 2.0 */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single delaySubscription(@NonNull CompletableSource other) { - Objects.requireNonNull(other, "other is null"); - return RxJavaPlugins.onAssembly(new SingleDelayWithCompletable<>(this, other)); + public final Single delaySubscription(@NonNull CompletableSource subscriptionIndicator) { + Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); + return RxJavaPlugins.onAssembly(new SingleDelayWithCompletable<>(this, subscriptionIndicator)); } /** @@ -2323,18 +2324,18 @@ public final Single delaySubscription(@NonNull CompletableSource other) { *
{@code delaySubscription} does not operate by default on a particular {@link Scheduler}.
* * @param the element type of the other source - * @param other the {@code SingleSource} that has to complete before the subscription to the + * @param subscriptionIndicator the {@code SingleSource} that has to complete before the subscription to the * current {@code Single} happens * @return the new {@code Single} instance - * @throws NullPointerException if {@code other} is {@code null} + * @throws NullPointerException if {@code subscriptionIndicator} is {@code null} * @since 2.0 */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single delaySubscription(@NonNull SingleSource other) { - Objects.requireNonNull(other, "other is null"); - return RxJavaPlugins.onAssembly(new SingleDelayWithSingle<>(this, other)); + public final Single delaySubscription(@NonNull SingleSource subscriptionIndicator) { + Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); + return RxJavaPlugins.onAssembly(new SingleDelayWithSingle<>(this, subscriptionIndicator)); } /** @@ -2349,18 +2350,18 @@ public final Single delaySubscription(@NonNull SingleSource other) { *
{@code delaySubscription} does not operate by default on a particular {@link Scheduler}.
* * @param the element type of the other source - * @param other the {@code ObservableSource} that has to signal a value or complete before the + * @param subscriptionIndicator the {@code ObservableSource} that has to signal a value or complete before the * subscription to the current {@code Single} happens * @return the new {@code Single} instance - * @throws NullPointerException if {@code other} is {@code null} + * @throws NullPointerException if {@code subscriptionIndicator} is {@code null} * @since 2.0 */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single delaySubscription(@NonNull ObservableSource other) { - Objects.requireNonNull(other, "other is null"); - return RxJavaPlugins.onAssembly(new SingleDelayWithObservable<>(this, other)); + public final Single delaySubscription(@NonNull ObservableSource subscriptionIndicator) { + Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); + return RxJavaPlugins.onAssembly(new SingleDelayWithObservable<>(this, subscriptionIndicator)); } /** @@ -2379,19 +2380,19 @@ public final Single delaySubscription(@NonNull ObservableSource other) *
{@code delaySubscription} does not operate by default on a particular {@link Scheduler}.
* * @param the element type of the other source - * @param other the {@code Publisher} that has to signal a value or complete before the + * @param subscriptionIndicator the {@code Publisher} that has to signal a value or complete before the * subscription to the current {@code Single} happens * @return the new {@code Single} instance - * @throws NullPointerException if {@code other} is {@code null} + * @throws NullPointerException if {@code subscriptionIndicator} is {@code null} * @since 2.0 */ @BackpressureSupport(BackpressureKind.FULL) @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single delaySubscription(@NonNull Publisher other) { - Objects.requireNonNull(other, "other is null"); - return RxJavaPlugins.onAssembly(new SingleDelayWithPublisher<>(this, other)); + public final Single delaySubscription(@NonNull Publisher subscriptionIndicator) { + Objects.requireNonNull(subscriptionIndicator, "subscriptionIndicator is null"); + return RxJavaPlugins.onAssembly(new SingleDelayWithPublisher<>(this, subscriptionIndicator)); } /** @@ -3154,15 +3155,16 @@ public final Single> materialize() { *
Scheduler:
*
{@code contains} does not operate by default on a particular {@link Scheduler}.
* - * @param value the value to compare against the success value of this {@code Single} + * @param item the value to compare against the success value of this {@code Single} * @return the new {@code Single} instance + * @throws NullPointerException if {@code item} is {@code null} * @since 2.0 */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public final Single contains(@NonNull Object value) { - return contains(value, ObjectHelper.equalsPredicate()); + public final Single contains(@NonNull Object item) { + return contains(item, ObjectHelper.equalsPredicate()); } /** @@ -3174,20 +3176,20 @@ public final Single contains(@NonNull Object value) { *
Scheduler:
*
{@code contains} does not operate by default on a particular {@link Scheduler}.
* - * @param value the value to compare against the success value of this {@code Single} + * @param item the value to compare against the success value of this {@code Single} * @param comparer the function that receives the success value of this {@code Single}, the value provided * and should return {@code true} if they are considered equal * @return the new {@code Single} instance - * @throws NullPointerException if {@code value} or {@code comparer} is {@code null} + * @throws NullPointerException if {@code item} or {@code comparer} is {@code null} * @since 2.0 */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single contains(@NonNull Object value, @NonNull BiPredicate comparer) { - Objects.requireNonNull(value, "value is null"); + public final Single contains(@NonNull Object item, @NonNull BiPredicate comparer) { + Objects.requireNonNull(item, "item is null"); Objects.requireNonNull(comparer, "comparer is null"); - return RxJavaPlugins.onAssembly(new SingleContains<>(this, value, comparer)); + return RxJavaPlugins.onAssembly(new SingleContains<>(this, item, comparer)); } /** @@ -3264,19 +3266,19 @@ public final Single observeOn(@NonNull Scheduler scheduler) { *
{@code onErrorReturn} does not operate by default on a particular {@link Scheduler}.
* * - * @param resumeFunction + * @param itemSupplier * a function that returns an item that the new {@code Single} will emit if the current {@code Single} encounters * an error * @return the new {@code Single} instance - * @throws NullPointerException if {@code resumeFunction} is {@code null} + * @throws NullPointerException if {@code itemSupplier} is {@code null} * @see ReactiveX operators documentation: Catch */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single onErrorReturn(@NonNull Function resumeFunction) { - Objects.requireNonNull(resumeFunction, "resumeFunction is null"); - return RxJavaPlugins.onAssembly(new SingleOnErrorReturn<>(this, resumeFunction, null)); + public final Single onErrorReturn(@NonNull Function itemSupplier) { + Objects.requireNonNull(itemSupplier, "itemSupplier is null"); + return RxJavaPlugins.onAssembly(new SingleOnErrorReturn<>(this, itemSupplier, null)); } /** @@ -3287,17 +3289,17 @@ public final Single onErrorReturn(@NonNull Function r *
Scheduler:
*
{@code onErrorReturnItem} does not operate by default on a particular {@link Scheduler}.
* - * @param value the value to signal if the current {@code Single} fails + * @param item the value to signal if the current {@code Single} fails * @return the new {@code Single} instance - * @throws NullPointerException if {@code value} is {@code null} + * @throws NullPointerException if {@code item} is {@code null} * @since 2.0 */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public final Single onErrorReturnItem(@NonNull T value) { - Objects.requireNonNull(value, "value is null"); - return RxJavaPlugins.onAssembly(new SingleOnErrorReturn<>(this, null, value)); + public final Single onErrorReturnItem(@NonNull T item) { + Objects.requireNonNull(item, "item is null"); + return RxJavaPlugins.onAssembly(new SingleOnErrorReturn<>(this, null, item)); } /** @@ -3359,9 +3361,9 @@ public final Single onErrorResumeWith(@NonNull SingleSource fall *
{@code onErrorResumeNext} does not operate by default on a particular {@link Scheduler}.
* * - * @param fallback a function that returns a {@code Single} that will take control if source {@code Single} encounters an error. + * @param fallbackSupplier a function that returns a {@code SingleSource} that will take control if source {@code Single} encounters an error. * @return the new {@code Single} instance - * @throws NullPointerException if {@code fallback} is {@code null} + * @throws NullPointerException if {@code fallbackSupplier} is {@code null} * @see ReactiveX operators documentation: Catch * @since .20 */ @@ -3369,9 +3371,9 @@ public final Single onErrorResumeWith(@NonNull SingleSource fall @NonNull @SchedulerSupport(SchedulerSupport.NONE) public final Single onErrorResumeNext( - @NonNull Function> fallback) { - Objects.requireNonNull(fallback, "fallback is null"); - return RxJavaPlugins.onAssembly(new SingleResumeNext<>(this, fallback)); + @NonNull Function> fallbackSupplier) { + Objects.requireNonNull(fallbackSupplier, "fallbackSupplier is null"); + return RxJavaPlugins.onAssembly(new SingleResumeNext<>(this, fallbackSupplier)); } /** diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecentTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecentTest.java index f652e9fbf6..82ae58730f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecentTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/BlockingFlowableMostRecentTest.java @@ -26,10 +26,6 @@ import io.reactivex.rxjava3.schedulers.TestScheduler; public class BlockingFlowableMostRecentTest extends RxJavaTest { - @Test - public void mostRecentNull() { - assertNull(Flowable.never().blockingMostRecent(null).iterator().next()); - } @Test public void mostRecent() { diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecentTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecentTest.java index 6ffd920f24..cc04638ee7 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecentTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/BlockingObservableMostRecentTest.java @@ -27,10 +27,6 @@ import io.reactivex.rxjava3.subjects.*; public class BlockingObservableMostRecentTest extends RxJavaTest { - @Test - public void mostRecentNull() { - assertNull(Observable.never().blockingMostRecent(null).iterator().next()); - } static Iterable mostRecent(Observable source, T initialValue) { return source.blockingMostRecent(initialValue); diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorArgumentNaming.java b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorArgumentNaming.java new file mode 100644 index 0000000000..727b522d05 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorArgumentNaming.java @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.util; + +import java.lang.reflect.*; +import java.util.*; + +import org.reactivestreams.*; + +import com.google.common.base.Strings; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.core.Observable; + +/** + * Compare method argument naming across base classes. + * This is not a full test because some naming mismatch is legitimate, such as singular in Maybe/Single and + * plural in Flowable/Observable + */ +public final class OperatorArgumentNaming { + + private OperatorArgumentNaming() { + throw new IllegalStateException("No instances!"); + } + + /** Classes to compare with each other. */ + static final Class[] CLASSES = { Flowable.class, Observable.class, Maybe.class, Single.class, Completable.class }; + + /** Types that refer to a reactive type and is generally matching the parent class; for comparison, these have to be unified. */ + static final Set> BASE_TYPE_SET = new HashSet<>(Arrays.asList( + Flowable.class, Publisher.class, Subscriber.class, FlowableSubscriber.class, + Observable.class, ObservableSource.class, Observer.class, + Maybe.class, MaybeSource.class, MaybeObserver.class, + Single.class, SingleSource.class, SingleObserver.class, + Completable.class, CompletableSource.class, CompletableObserver.class + )); + + public static void main(String[] args) { + // className -> methodName -> overloads -> arguments + Map>>> map = new HashMap<>(); + + for (Class clazz : CLASSES) { + Map>> classMethods = map.computeIfAbsent(clazz.getSimpleName(), v -> new HashMap<>()); + for (Method method : clazz.getDeclaredMethods()) { + if (method.getDeclaringClass() == clazz && method.getParameterCount() != 0) { + List> overloads = classMethods.computeIfAbsent(method.getName(), v -> new ArrayList<>()); + + List overload = new ArrayList<>(); + overloads.add(overload); + + for (Parameter param : method.getParameters()) { + String typeName; + Class type = param.getType(); + if (type.isArray()) { + Class componentType = type.getComponentType(); + if (BASE_TYPE_SET.contains(componentType)) { + typeName = "BaseType"; + } else { + typeName = type.getComponentType().getSimpleName() + "[]"; + } + } else + if (BASE_TYPE_SET.contains(type)) { + typeName = "BaseType"; + } else { + typeName = type.getSimpleName(); + } + String name = param.getName(); + if (name.equals("bufferSize") || name.equals("prefetch") || name.equals("capacityHint")) { + name = "bufferSize|prefetch|capacityHint"; + } + if (name.equals("subscriber") || name.equals("observer")) { + name = "subscriber|observer"; + } + if (name.contains("onNext")) { + name = name.replace("onNext", "onNext|onSuccess"); + } else + if (name.contains("onSuccess")) { + name = name.replace("onSuccess", "onNext|onSuccess"); + } + overload.add(new ArgumentNameAndType(typeName, name)); + } + } + } + } + + int counter = 0; + + for (int i = 0; i < CLASSES.length - 1; i++) { + String firstName = CLASSES[i].getSimpleName(); + Map>> firstClassMethods = map.get(firstName); + for (int j = i + 1; j < CLASSES.length; j++) { + String secondName = CLASSES[j].getSimpleName(); + Map>> secondClassMethods = map.get(secondName); + + for (Map.Entry>> methodOverloadsFirst : firstClassMethods.entrySet()) { + + List> methodOverloadsSecond = secondClassMethods.get(methodOverloadsFirst.getKey()); + + if (methodOverloadsSecond != null) { + for (List overloadFirst : methodOverloadsFirst.getValue()) { + for (List overloadSecond : methodOverloadsSecond) { + if (overloadFirst.size() == overloadSecond.size()) { + // Argument types match? + boolean match = true; + for (int k = 0; k < overloadFirst.size(); k++) { + if (!overloadFirst.get(k).type.equals(overloadSecond.get(k).type)) { + match = false; + break; + } + } + // Argument names match? + if (match) { + for (int k = 0; k < overloadFirst.size(); k++) { + if (!overloadFirst.get(k).name.equals(overloadSecond.get(k).name)) { + System.out.print("Argument naming mismatch #"); + System.out.println(++counter); + + System.out.print(" "); + System.out.print(Strings.padEnd(firstName, Math.max(firstName.length(), secondName.length()) + 1, ' ')); + System.out.print(methodOverloadsFirst.getKey()); + System.out.print(" "); + System.out.println(overloadFirst); + + System.out.print(" "); + System.out.print(Strings.padEnd(secondName, Math.max(firstName.length(), secondName.length()) + 1, ' ')); + System.out.print(methodOverloadsFirst.getKey()); + System.out.print(" "); + System.out.println(overloadSecond); + System.out.println(); + break; + } + } + } + } + } + } + } + } + } + } + } + + static final class ArgumentNameAndType { + final String type; + final String name; + + ArgumentNameAndType(String type, String name) { + this.type = type; + this.name = name; + } + + @Override + public String toString() { + return type + " " + name; + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java index f9becca37c..403a83964a 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java +++ b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java @@ -142,9 +142,6 @@ public void checkParallelFlowable() { addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "delay", Long.TYPE, TimeUnit.class, Scheduler.class)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "delay", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE)); - // null default is allowed - addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "blockingMostRecent", Object.class)); - // negative time is considered as zero time addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "delaySubscription", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Flowable.class, 0, ParamMode.ANY, "delaySubscription", Long.TYPE, TimeUnit.class, Scheduler.class)); @@ -390,9 +387,6 @@ public void checkParallelFlowable() { addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "delay", Long.TYPE, TimeUnit.class, Scheduler.class)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "delay", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE)); - // null default is allowed - addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "blockingMostRecent", Object.class)); - // negative time is considered as zero time addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "delaySubscription", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Observable.class, 0, ParamMode.ANY, "delaySubscription", Long.TYPE, TimeUnit.class, Scheduler.class)); diff --git a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java index fe6d215165..ba307d394d 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java +++ b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java @@ -203,7 +203,7 @@ static void processFile(Class clazz) throws Exception { int quote = line.indexOf('"', comma); - String message = line.substring(quote + 1, quote + 2 + paramName.length()); + String message = line.substring(quote + 1, Math.min(line.length(), quote + 2 + paramName.length())); if (line.contains("\"A Disposable")) { continue; From 13ffa189bb16149eec7a2fe23c03c5b35037f737 Mon Sep 17 00:00:00 2001 From: slisaasquatch Date: Tue, 21 Jan 2020 13:21:08 -0800 Subject: [PATCH 02/37] Rename Single.equals to Single.sequenceEqual (#6856) * Rename Single.equals to Single.sequenceEqual * Rename Single.sequenceEqual arguments * Update mentions of renamed parameters --- .../java/io/reactivex/rxjava3/core/Single.java | 16 ++++++++-------- .../operators/single/SingleEqualsTest.java | 2 +- .../operators/single/SingleMiscTest.java | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 0541ce8657..f915bdc5b2 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -1387,22 +1387,22 @@ public static Single timer(long delay, @NonNull TimeUnit unit, @NonNull Sc * *
*
Scheduler:
- *
{@code equals} does not operate by default on a particular {@link Scheduler}.
+ *
{@code sequenceEqual} does not operate by default on a particular {@link Scheduler}.
*
* @param the common value type - * @param first the first {@code SingleSource} instance - * @param second the second {@code SingleSource} instance + * @param source1 the first {@code SingleSource} instance + * @param source2 the second {@code SingleSource} instance * @return the new {@code Single} instance - * @throws NullPointerException if {@code first} or {@code second} is {@code null} + * @throws NullPointerException if {@code source1} or {@code source2} is {@code null} * @since 2.0 */ @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - public static Single equals(@NonNull SingleSource first, @NonNull SingleSource second) { // NOPMD - Objects.requireNonNull(first, "first is null"); - Objects.requireNonNull(second, "second is null"); - return RxJavaPlugins.onAssembly(new SingleEquals<>(first, second)); + public static Single sequenceEqual(@NonNull SingleSource source1, @NonNull SingleSource source2) { // NOPMD + Objects.requireNonNull(source1, "source1 is null"); + Objects.requireNonNull(source2, "source2 is null"); + return RxJavaPlugins.onAssembly(new SingleEquals<>(source1, source2)); } /** diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleEqualsTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleEqualsTest.java index c664784869..6c1bf14f30 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleEqualsTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleEqualsTest.java @@ -28,7 +28,7 @@ public class SingleEqualsTest extends RxJavaTest { public void bothError() { List errors = TestHelper.trackPluginErrors(); try { - Single.equals(Single.error(new TestException("One")), Single.error(new TestException("Two"))) + Single.sequenceEqual(Single.error(new TestException("One")), Single.error(new TestException("Two"))) .to(TestHelper.testConsumer()) .assertFailureAndMessage(TestException.class, "One"); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMiscTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMiscTest.java index ca2ccacdc2..dad1322b22 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMiscTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMiscTest.java @@ -280,11 +280,11 @@ public void toObservable() { @Test public void equals() { - Single.equals(Single.just(1), Single.just(1).hide()) + Single.sequenceEqual(Single.just(1), Single.just(1).hide()) .test() .assertResult(true); - Single.equals(Single.just(1), Single.just(2)) + Single.sequenceEqual(Single.just(1), Single.just(2)) .test() .assertResult(false); } From b6aceec436ee1dcc9ff904bb14be6698f65130e7 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Wed, 22 Jan 2020 14:03:30 +0100 Subject: [PATCH 03/37] 3.x: Verify the use of base interfaces in operator inputs & lambdas (#6858) * 3.x: Verify the use of base interfaces in operator inputs & lambdas * Add @NonNull annotations too. --- .../io/reactivex/rxjava3/core/Flowable.java | 4 +- .../validators/OperatorsUseInterfaces.java | 189 ++++++++++++++++++ 2 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 src/test/java/io/reactivex/rxjava3/validators/OperatorsUseInterfaces.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Flowable.java b/src/main/java/io/reactivex/rxjava3/core/Flowable.java index 038c3f680b..5f5aff68c6 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Flowable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Flowable.java @@ -6790,7 +6790,7 @@ public final Flowable> buffer(long timespan, @NonNull TimeUnit unit, @No @SchedulerSupport(SchedulerSupport.NONE) @NonNull public final Flowable> buffer( - @NonNull Flowable openingIndicator, + @NonNull Publisher<@NonNull ? extends TOpening> openingIndicator, @NonNull Function> closingIndicator) { return buffer(openingIndicator, closingIndicator, ArrayListSupplier.asSupplier()); } @@ -6831,7 +6831,7 @@ public final Flowable> buffer( @SchedulerSupport(SchedulerSupport.NONE) @NonNull public final > Flowable buffer( - @NonNull Flowable openingIndicator, + @NonNull Publisher<@NonNull ? extends TOpening> openingIndicator, @NonNull Function> closingIndicator, @NonNull Supplier bufferSupplier) { Objects.requireNonNull(openingIndicator, "openingIndicator is null"); diff --git a/src/test/java/io/reactivex/rxjava3/validators/OperatorsUseInterfaces.java b/src/test/java/io/reactivex/rxjava3/validators/OperatorsUseInterfaces.java new file mode 100644 index 0000000000..e521c15b6e --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/validators/OperatorsUseInterfaces.java @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.validators; + +import static org.junit.Assert.*; + +import java.lang.reflect.*; +import java.util.*; +import java.util.Observable; +import java.util.concurrent.Callable; + +import org.junit.Test; +import org.reactivestreams.Publisher; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.parallel.ParallelFlowable; + +/** + * Verify that an operator method uses base interfaces as its direct input or + * has lambdas returning base interfaces. + */ +public class OperatorsUseInterfaces { + + @Test + public void checkFlowable() { + checkClass(Flowable.class); + } + + @Test + public void checkObservable() { + checkClass(Observable.class); + } + + @Test + public void checkMaybe() { + checkClass(Maybe.class); + } + + @Test + public void checkSingle() { + checkClass(Single.class); + } + + @Test + public void checkCompletable() { + checkClass(Completable.class); + } + + @Test + public void checkParallelFlowable() { + checkClass(ParallelFlowable.class); + } + + void checkClass(Class clazz) { + StringBuilder error = new StringBuilder(); + int errors = 0; + + for (Method method : clazz.getMethods()) { + if (method.getDeclaringClass() == clazz) { + int pidx = 1; + for (Parameter param : method.getParameters()) { + Class type = param.getType(); + if (type.isArray()) { + type = type.getComponentType(); + } + if (CLASSES.contains(type)) { + errors++; + error.append("Non-interface input parameter #") + .append(pidx) + .append(": ") + .append(type) + .append("\r\n") + .append(" ") + .append(method) + .append("\r\n") + ; + } + if (CAN_RETURN.contains(type)) { + Type gtype = method.getGenericParameterTypes()[pidx - 1]; + if (gtype instanceof GenericArrayType) { + gtype = ((GenericArrayType)gtype).getGenericComponentType(); + } + ParameterizedType ptype = (ParameterizedType)gtype; + for (;;) { + Type[] parameterArgTypes = ptype.getActualTypeArguments(); + Type argType = parameterArgTypes[parameterArgTypes.length - 1]; + if (argType instanceof GenericArrayType) { + argType = ((GenericArrayType)argType).getGenericComponentType(); + } + if (argType instanceof ParameterizedType) { + ParameterizedType lastArg = (ParameterizedType)argType; + + if (CLASSES.contains(lastArg.getRawType())) { + errors++; + error.append("Non-interface lambda return #") + .append(pidx) + .append(": ") + .append(type) + .append("\r\n") + .append(" ") + .append(method) + .append("\r\n") + ; + } + + if (CAN_RETURN.contains(lastArg.getRawType())) { + ptype = lastArg; + continue; + } + } + break; + } + } + pidx++; + } + } + } + + if (errors != 0) { + error.insert(0, "Found " + errors + " issues\r\n"); + fail(error.toString()); + } + } + + public void method1(Flowable f) { + // self-test + } + + public void method2(Callable> c) { + // self-test + } + + public void method3(Supplier>> c) { + // self-test + } + + public void method4(Flowable[] array) { + // self-test + } + + public void method5(Callable[]> c) { + // self-test + } + + public void method6(Callable[]>> c) { + // self-test + } + + @Test + public void checkSelf() { + try { + checkClass(OperatorsUseInterfaces.class); + throw new RuntimeException("Should have failed"); + } catch (AssertionError expected) { + assertTrue(expected.toString(), expected.toString().contains("method1")); + assertTrue(expected.toString(), expected.toString().contains("method2")); + assertTrue(expected.toString(), expected.toString().contains("method3")); + assertTrue(expected.toString(), expected.toString().contains("method4")); + assertTrue(expected.toString(), expected.toString().contains("method5")); + assertTrue(expected.toString(), expected.toString().contains("method6")); + } + } + + static final Set> CLASSES = new HashSet<>(Arrays.asList( + Flowable.class, Observable.class, + Maybe.class, Single.class, + Completable.class + )); + + static final Set> CAN_RETURN = new HashSet<>(Arrays.asList( + Callable.class, Supplier.class, + Function.class, BiFunction.class, Function3.class, Function4.class, + Function5.class, Function6.class, Function7.class, Function8.class, + Function9.class, + Publisher.class, ObservableSource.class, MaybeSource.class, SingleSource.class + )); +} From 99de2aa77c9b29620177397190ded1211e4fc772 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Wed, 22 Jan 2020 14:03:53 +0100 Subject: [PATCH 04/37] 3.x: [Wiki] Improve Operator-Matrix with links and notes (#6857) --- docs/Operator-Matrix.md | 587 +++++++++++------- .../util/OperatorMatrixGenerator.java | 385 +++++++++++- 2 files changed, 727 insertions(+), 245 deletions(-) diff --git a/docs/Operator-Matrix.md b/docs/Operator-Matrix.md index ded48d8509..832d64311d 100644 --- a/docs/Operator-Matrix.md +++ b/docs/Operator-Matrix.md @@ -1,240 +1,347 @@ -Operator | `Flowable` | `Observable` | `Maybe` | `Single` | `Completable` | ------|:---:|:---:|:---:|:---:|:---:| -`all`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`amb`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`ambArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`ambWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`andThen`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`any`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingAwait`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`blockingFirst`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingForEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingGet`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingMostRecent`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`blockingSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`buffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`cache`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`cacheWithInitialCapacity`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`cast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`collect`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`collectInto`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`combineLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`combineLatestArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`combineLatestArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`combineLatestDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`complete`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`compose`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`concat`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`concatArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`concatArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatArrayEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatArrayEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`contains`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`count`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`create`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`debounce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`defaultIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`defer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`delay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`delaySubscription`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`dematerialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`distinct`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`distinctUntilChanged`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`doAfterNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`doAfterSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`doAfterTerminate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doFinally`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnCancel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`doOnComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnDispose`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`doOnError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnEvent`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnLifecycle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`doOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`doOnRequest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`doOnSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`doOnTerminate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`elementAt`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`elementAtOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`empty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`equals`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`error`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`filter`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`first`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`firstElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`firstOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`firstOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`firstStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flatMapObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flatMapPublisher`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flatMapSingleElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flattenAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flattenAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flattenStreamAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`flattenStreamAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`forEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`forEachWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`fromAction`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`fromCallable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromCompletable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`fromCompletionStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`fromMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`fromPublisher`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromRunnable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`fromSupplier`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`generate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`groupBy`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`groupJoin`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`hide`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`ignoreElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`ignoreElements`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`interval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`intervalRange`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`isEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`join`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`just`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`last`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`lastElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`lastOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`lastOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`lastStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`lift`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`map`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`mapOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`materialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`merge`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`mergeArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`mergeArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`mergeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`mergeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`never`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`observeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`ofType`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`onBackpressureBuffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`onBackpressureDrop`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`onBackpressureLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`onErrorComplete`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`onErrorResumeNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`onErrorResumeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`onErrorReturn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`onErrorReturnItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`onTerminateDetach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`parallel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`publish`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`range`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`rangeLong`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`rebatchRequests`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`reduce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`reduceWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`repeat`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`repeatUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`repeatWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`replay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`retry`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`retryUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`retryWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`safeSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`scan`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`scanWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`sequenceEqual`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`serialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`share`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`single`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`singleElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`singleOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`singleOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`singleStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`skip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`skipLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`skipUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`skipWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`sorted`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`startWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`startWithArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`startWithItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`startWithIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`subscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`subscribeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`subscribeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`switchIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchOnNextDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`take`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`takeLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`takeUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`takeWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`test`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`throttleFirst`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`throttleLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`throttleLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`throttleWithTimeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`timeInterval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`timeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`timer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`to`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toCompletionStage`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`toList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`toMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`toMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toMultimap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`toObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toSingleDefault`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toSortedList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`unsafeCreate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`unsubscribeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`using`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`window`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`withLatestFrom`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`wrap`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmatrix-flowable.png) | ![Observable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmatrix-observable.png) | ![Maybe](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmatrix-maybe.png) | ![Single](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmatrix-single.png) | ![Completable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmatrix-completable.png) | +-----|---|---|---|---|---| +`all`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([1](#notes-1))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([1](#notes-1))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`amb`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`ambArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`ambWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`andThen`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([3](#notes-3))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([3](#notes-3))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([3](#notes-3))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([3](#notes-3))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`any`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([1](#notes-1))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([1](#notes-1))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`blockingAwait`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([4](#notes-4))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([4](#notes-4))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([5](#notes-5))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([5](#notes-5))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`blockingFirst`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| +`blockingForEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([8](#notes-8))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([8](#notes-8))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([8](#notes-8))| +`blockingGet`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([4](#notes-4))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([4](#notes-4))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| +`blockingIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| +`blockingLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| +`blockingLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| +`blockingMostRecent`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| +`blockingNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| +`blockingSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| +`blockingStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| +`blockingSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`buffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([9](#notes-9))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([10](#notes-10))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([11](#notes-11))| +`cache`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`cacheWithInitialCapacity`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([12](#notes-12))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([12](#notes-12))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([12](#notes-12))| +`cast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`collect`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| +`collectInto`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| +`combineLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([16](#notes-16))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([16](#notes-16))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([17](#notes-17))| +`combineLatestArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([18](#notes-18))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([18](#notes-18))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([19](#notes-19))| +`combineLatestArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([18](#notes-18))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([18](#notes-18))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([20](#notes-20))| +`combineLatestDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([16](#notes-16))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([16](#notes-16))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([21](#notes-21))| +`complete`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([22](#notes-22))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([22](#notes-22))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([22](#notes-22))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`compose`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`concat`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`concatArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`concatArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`concatArrayEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([24](#notes-24))| +`concatArrayEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([25](#notes-25))| +`concatDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`concatEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([26](#notes-26))| +`concatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`concatMapEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`concatMapEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`concatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`contains`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`count`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))| +`create`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`debounce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`defaultIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))| +`defer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`delay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`delaySubscription`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`dematerialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`distinct`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`distinctUntilChanged`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`doAfterNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`doAfterSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`doAfterTerminate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doFinally`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnCancel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| +`doOnComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnDispose`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`doOnError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnEvent`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnLifecycle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`doOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`doOnRequest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))| +`doOnSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`doOnTerminate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`elementAt`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`elementAtOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`empty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))| +`equals`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`error`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`filter`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`first`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))| +`firstElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`firstOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))| +`firstOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| +`firstStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))| +`flatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapPublisher`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapSingleElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenStreamAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenStreamAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`forEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| +`forEachWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| +`fromAction`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| +`fromCallable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromCompletable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))| +`fromCompletionStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| +`fromMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| +`fromPublisher`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromRunnable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| +`fromSupplier`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`generate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))| +`groupBy`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| +`groupJoin`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))| +`hide`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`ignoreElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`ignoreElements`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`interval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))| +`intervalRange`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))| +`isEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`join`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([76](#notes-76))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([76](#notes-76))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))| +`just`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`last`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))| +`lastElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`lastOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))| +`lastOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| +`lastStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))| +`lift`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`map`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`mapOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`materialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`merge`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`mergeArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`mergeArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`mergeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`mergeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`never`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`observeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`ofType`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([77](#notes-77))| +`onBackpressureBuffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))| +`onBackpressureDrop`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))| +`onBackpressureLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))| +`onErrorComplete`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`onErrorResumeNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`onErrorResumeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`onErrorReturn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`onErrorReturnItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`onTerminateDetach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`parallel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))| +`publish`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))| +`range`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| +`rangeLong`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| +`rebatchRequests`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))| +`reduce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))| +`reduceWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))| +`repeat`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`repeatUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`repeatWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`replay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))| +`retry`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`retryUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`retryWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`safeSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`scan`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))| +`scanWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))| +`sequenceEqual`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`serialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))| +`share`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))| +`single`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))| +`singleElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`singleOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))| +`singleOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| +`singleStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))| +`skip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| +`skipLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| +`skipUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| +`skipWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`sorted`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))| +`startWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`startWithArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))| +`startWithItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| +`startWithIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))| +`subscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`subscribeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`subscribeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`switchIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))| +`switchMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`switchOnNextDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`take`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| +`takeLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| +`takeUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`takeWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`test`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`throttleFirst`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`throttleLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`throttleLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`throttleWithTimeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`timeInterval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`timeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`timer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`to`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toCompletionStage`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`toList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| +`toMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| +`toMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toMultimap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| +`toObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toSingleDefault`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toSortedList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| +`unsafeCreate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`unsubscribeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`using`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`window`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([101](#notes-101))| +`withLatestFrom`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([16](#notes-16))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([16](#notes-16))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([17](#notes-17))| +`wrap`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([103](#notes-103))| +`zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([104](#notes-104))| +`zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([105](#notes-105))| + +#### Notes +1 Use [`contains()`](#contains).
+2 Always empty.
+3 Use [`concatWith`](#concatWith).
+4 Use [`blockingFirst()`](#blockingFirst), [`blockingSingle()`](#blockingSingle) or [`blockingLast()`](#blockingLast).
+5 Use [`blockingGet()`](#blockingGet).
+6 At most one element to get. Use [`blockingGet()`](#blockingGet).
+7 No elements to get. Use [`blockingAwait()`](#blockingAwait).
+8 Use [`blockingSubscribe()`](#blockingSubscribe)
+9 Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a list/collection.
+10 Use [`map()`](#map) to transform into a list/collection.
+11 Always empty. Use [`andThen()`](#andThen) to bring in a list/collection.
+12 At most one element to store. Use [`cache()`](#cache).
+13 At most one element to collect. Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a list/collection.
+14 One element to collect. Use [`map()`](#map) to transform into a list/collection.
+15 Always empty. Use [`andThen()`](#andThen) to bring in a collection.
+16 At most one element per source. Use [`zip()`](#zip).
+17 Always empty. Use [`merge()`](#merge).
+18 At most one element per source. Use [`zipArray()`](#zipArray).
+19 Always empty. Use [`mergeArray()`](#mergeArray).
+20 Always empty. Use [`mergeArrayDelayError()`](#mergeArrayDelayError).
+21 Always empty. Use [`mergeDelayError()`](#mergeDelayError).
+22 Use [`empty()`](#empty).
+23 Never empty.
+24 No items to keep ordered. Use [`mergeArray()`](#mergeArray).
+25 No items to keep ordered. Use [`mergeArrayDelayError()`](#mergeArrayDelayError).
+26 No items to keep ordered. Use [`merge()`](#merge).
+27 Always empty thus no items to map.
+28 At most one item. Use [`flattenAsFlowable`](#flattenAsFlowable) or [`flattenAsObservable`](#flattenAsObservable).
+29 At most one item. Use [`flattenStreamAsFlowable`](#flattenStreamAsFlowable) or [`flattenStreamAsObservable`](#flattenStreamAsObservable).
+30 Never empty thus always 1.
+31 Always empty thus always 0.
+32 At most one item signaled so no subsequent items to work with.
+33 Always empty thus no items to work with.
+34 Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.
+35 At most one item, always distinct.
+36 Different terminology. Use [`doAfterSuccess()`](#doAfterSuccess).
+37 Different terminology. Use [`doAfterNext()`](#doAfterNext).
+38 Different terminology. Use [`doOnDispose()`](#doOnDispose).
+39 Always succeeds or fails, there is no `onComplete` signal.
+40 Different terminology. Use [`doOnCancel()`](#doOnCancel).
+41 At most one item. Use [`doOnEvent()`](#doOnEvent).
+42 Use [`doOnEach()`](#doOnEach).
+43 Different terminology. Use [`doOnSuccess()`](#doOnSuccess).
+44 Backpressure related and not supported outside `Flowable`.
+45 Different terminology. Use [`doOnNext()`](#doOnNext).
+46 At most one item with index 0. Use [`defaultIfEmpty`](#defaultIfEmpty).
+47 Always one item with index 0.
+48 At most one item with index 0. Use [`toSingle`](#toSingle).
+49 Use [`complete()`](#complete).
+50 At most one item. Use [`defaultIfEmpty`](#defaultIfEmpty).
+51 Always one item.
+52 At most one item, would be no-op.
+53 Always one item, would be no-op.
+54 Always empty. Use [`andThen()`](#andThen) and [`error()`](#error).
+55 At most one item. Use [`toCompletionStage()`](#toCompletionStage).
+56 Always empty. Use [`andThen()`](#andThen), [`error()`](#error) and [`toCompletionStage()`](#toCompletionStage).
+57 Not supported. Use [`flatMap`](#flatMap) and [`toFlowable()`](#toFlowable).
+58 Use [`flatMap`](#flatMap).
+59 Not supported. Use [`flatMap`](#flatMap) and [`toObservable()`](#toFlowable).
+60 Use [`flatMapSingle`](#flatMapSingle).
+61 Use [`flatMapIterable()`](#flatMapIterable).
+62 Use [`flatMapStream()`](#flatMapStream).
+63 Use [`subscribe()`](#subscribe).
+64 At most one item. Use [`just()`](#just) or [`empty()`](#empty).
+65 Always one item. Use [`just()`](#just).
+66 Always empty. Use [`complete()`](#complete).
+67 Always error.
+68 Use [`wrap()`](#wrap).
+69 Use [`fromSupplier()`](#fromSupplier).
+70 At most one item.
+71 Always empty thus no items to group.
+72 Always empty thus no items to join.
+73 Use [`ignoreElements()`](#ignoreElements).
+74 Use [`ignoreElement()`](#ignoreElement).
+75 At most one item. Use [`timer()`](#timer).
+76 At most one item. Use [`zip()`](#zip)
+77 Always empty thus no items to filter.
+78 Needs backpressure thus not supported outside `Flowable`.
+79 Connectable sources not supported outside `Flowable` and `Observable`. Use a `MaybeSubject`.
+80 Connectable sources not supported outside `Flowable` and `Observable`. Use a `SingleSubject`.
+81 Connectable sources not supported outside `Flowable` and `Observable`. Use a `ConnectableSubject`.
+82 At most one item. Use [`just()`](#just).
+83 At most one item. Use [`map()`](#map).
+84 Always empty thus no items to reduce.
+85 At most one signal type.
+86 At most one item. Use [`takeUntil()`](#takeUntil).
+87 At most one item. Use [`filter()`](#filter).
+88 Use [`startWith()`](#startWith) and [`fromArray()`](#fromArray) of `Flowable` or `Observable`.
+89 Use [`startWith()`](#startWith) and [`just()`](#just) of another reactive type.
+90 Use [`startWith()`](#startWith) and [`fromIterable()`](#fromArray) of `Flowable` or `Observable`.
+91 Always empty. Use [`defaultIfEmpty()`](#defaultIfEmpty).
+92 At most one item. Use [`flatMap()`](#flatMap).
+93 Use [`firstStage`](#firstStage), [`lastStage`](#lastStage) or [`singleStage`](#singleStage).
+94 Use [`firstElement`](#firstElement), [`lastElement`](#lastElement) or [`singleElement`](#singleElement).
+95 Would be no-op.
+96 Use [`firstOrError`](#firstOrError), [`lastOrError`](#lastOrError) or [`singleOrError`](#singleOrError).
+97 Use [`first`](#first), [`last`](#last) or [`single`](#single).
+98 Use [`defaultIfEmpty()`](#defaultIfEmpty).
+99 Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a nested source.
+100 Use [`map()`](#map) to transform into a nested source.
+101 Always empty. Use [`andThen()`](#andThen) to bring in a nested source.
+102 Use [`fromPublisher()`](#fromPublisher).
+103 Use [`merge()`](#merge).
+104 Use [`mergeArray()`](#mergeArray).
+105 Use [`mergeWith()`](#mergeWith).
diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java index 42ea23dd1d..1273a5b441 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java @@ -40,6 +40,10 @@ private OperatorMatrixGenerator() { Flowable.class, Observable.class, Maybe.class, Single.class, Completable.class }; + static String header(String type) { + return "![" + type + "](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmatrix-" + type.toLowerCase() + ".png)"; + } + public static void main(String[] args) throws IOException { Set operatorSet = new HashSet<>(); Map, Set> operatorMap = new HashMap<>(); @@ -64,18 +68,24 @@ public static void main(String[] args) throws IOException { try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(Paths.get("docs", "Operator-Matrix.md"), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING))) { out.print("Operator |"); for (Class clazz : CLASSES) { - out.print(" `"); - out.print(clazz.getSimpleName()); - out.print("` |"); + out.print(" "); + out.print(header(clazz.getSimpleName())); + out.print(" |"); } out.println(); out.print("-----|"); for (int i = 0; i < CLASSES.length; i++) { - out.print(":---:|"); + out.print("---|"); } out.println(); + + Map notesMap = new HashMap<>(); + List notesList = new ArrayList<>(); + for (String operatorName : sortedOperators) { - out.print("`"); + out.print("`"); out.print(operatorName); out.print("`|"); for (Class clazz : CLASSES) { @@ -83,11 +93,376 @@ public static void main(String[] args) throws IOException { out.print(PRESENT); } else { out.print(ABSENT); + String notes = findNotes(clazz.getSimpleName(), operatorName); + if (notes != null) { + Integer index = notesMap.get(notes); + if (index == null) { + index = notesMap.size() + 1; + notesMap.put(notes, index); + notesList.add(notes); + } + out.print(" (["); + out.print(index); + out.print("](#notes-"); + out.print(index); + out.print("))"); + } } out.print("|"); } out.println(); } + + if (!notesList.isEmpty()) { + out.println(); + out.println("#### Notes"); + + for (int i = 0; i < notesList.size(); i++) { + out.print(""); + out.print(i + 1); + out.print(" "); + out.print(notesList.get(i)); + out.println("
"); + } + } + } + } + + static String findNotes(String clazzName, String operatorName) { + Map classNotes = NOTES_MAP.get(operatorName); + if (classNotes != null) { + return classNotes.get(clazzName.substring(0, 1)); + } + switch (operatorName) { + case "empty": { + if ("Completable".equals(clazzName)) { + return "Use [`complete()`](#complete)."; + } + if ("Single".equals(clazzName)) { + return "Never empty."; + } + break; + } + } + return null; + } + + static final String[] NOTES = { + // Format + // FOMSC methodName note + " MS all Use [`contains()`](#contains).", + " C all Always empty.", + "FOMS andThen Use [`concatWith`](#concatWith).", + " MS any Use [`contains()`](#contains).", + " C any Always empty.", + "FO blockingAwait Use [`blockingFirst()`](#blockingFirst), [`blockingSingle()`](#blockingSingle) or [`blockingLast()`](#blockingLast).", + " MS blockingAwait Use [`blockingGet()`](#blockingGet).", + " MS blockingFirst At most one element to get. Use [`blockingGet()`](#blockingGet).", + " C blockingFirst No elements to get. Use [`blockingAwait()`](#blockingAwait).", + " MSC blockingForEach Use [`blockingSubscribe()`](#blockingSubscribe)", + "FO blockingGet Use [`blockingFirst()`](#blockingFirst), [`blockingSingle()`](#blockingSingle) or [`blockingLast()`](#blockingLast).", + " C blockingGet No elements to get. Use [`blockingAwait()`](#blockingAwait).", + " MS blockingIterable At most one element to get. Use [`blockingGet()`](#blockingGet).", + " C blockingIterable No elements to get. Use [`blockingAwait()`](#blockingAwait).", + " MS blockingLast At most one element to get. Use [`blockingGet()`](#blockingGet).", + " C blockingLast No elements to get. Use [`blockingAwait()`](#blockingAwait).", + " MS blockingLatest At most one element to get. Use [`blockingGet()`](#blockingGet).", + " C blockingLatest No elements to get. Use [`blockingAwait()`](#blockingAwait).", + " MS blockingMostRecent At most one element to get. Use [`blockingGet()`](#blockingGet).", + " C blockingMostRecent No elements to get. Use [`blockingAwait()`](#blockingAwait).", + " MS blockingNext At most one element to get. Use [`blockingGet()`](#blockingGet).", + " C blockingNext No elements to get. Use [`blockingAwait()`](#blockingAwait).", + " MS blockingSingle At most one element to get. Use [`blockingGet()`](#blockingGet).", + " C blockingSingle No elements to get. Use [`blockingAwait()`](#blockingAwait).", + " MS blockingStream At most one element to get. Use [`blockingGet()`](#blockingGet).", + " C blockingStream No elements to get. Use [`blockingAwait()`](#blockingAwait).", + " M buffer Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a list/collection.", + " S buffer Use [`map()`](#map) to transform into a list/collection.", + " C buffer Always empty. Use [`andThen()`](#andThen) to bring in a list/collection.", + " MSC cacheWithInitialCapacity At most one element to store. Use [`cache()`](#cache).", + " C cast Always empty.", + " M collect At most one element to collect. Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a list/collection.", + " S collect One element to collect. Use [`map()`](#map) to transform into a list/collection.", + " C collect Always empty. Use [`andThen()`](#andThen) to bring in a collection.", + " M collectInto At most one element to collect. Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a list/collection.", + " S collectInto One element to collect. Use [`map()`](#map) to transform into a list/collection.", + " C collectInto Always empty. Use [`andThen()`](#andThen) to bring in a collection.", + " MS combineLatest At most one element per source. Use [`zip()`](#zip).", + " C combineLatest Always empty. Use [`merge()`](#merge).", + " MS combineLatestArray At most one element per source. Use [`zipArray()`](#zipArray).", + " C combineLatestArray Always empty. Use [`mergeArray()`](#mergeArray).", + " MS combineLatestDelayError At most one element per source. Use [`zip()`](#zip).", + " C combineLatestDelayError Always empty. Use [`mergeDelayError()`](#mergeDelayError).", + " MS combineLatestArrayDelayError At most one element per source. Use [`zipArray()`](#zipArray).", + " C combineLatestArrayDelayError Always empty. Use [`mergeArrayDelayError()`](#mergeArrayDelayError).", + "FOM complete Use [`empty()`](#empty).", + " S complete Never empty.", + " C concatArrayEager No items to keep ordered. Use [`mergeArray()`](#mergeArray).", + " C concatArrayEagerDelayError No items to keep ordered. Use [`mergeArrayDelayError()`](#mergeArrayDelayError).", + " C concatEager No items to keep ordered. Use [`merge()`](#merge).", + " C concatEagerDelayError No items to keep ordered. Use [`mergeDelayError()`](#mergeDelayError).", + " C concatMap Always empty thus no items to map.", + " C concatMapCompletable Always empty thus no items to map.", + " C concatMapCompletableDelayError Always empty thus no items to map.", + " C concatMapIterable Always empty thus no items to map.", + " C concatMapMaybe Always empty thus no items to map.", + " C concatMapMaybeDelayError Always empty thus no items to map.", + " C concatMapSingle Always empty thus no items to map.", + " C concatMapSingleDelayError Always empty thus no items to map.", + " C concatMapStream Always empty thus no items to map.", + " MS concatMapIterable At most one item. Use [`flattenAsFlowable`](#flattenAsFlowable) or [`flattenAsObservable`](#flattenAsObservable).", + " MS concatMapStream At most one item. Use [`flattenStreamAsFlowable`](#flattenStreamAsFlowable) or [`flattenStreamAsObservable`](#flattenStreamAsObservable).", + " C contains Always empty.", + " S count Never empty thus always 1.", + " C count Always empty thus always 0.", + " MS debounce At most one item signaled so no subsequent items to work with.", + " C debounce Always empty thus no items to work with.", + " S defaultIfEmpty Never empty.", + " C defaultIfEmpty Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.", + " C dematerialize Always empty thus no items to work with.", + " MS distinct At most one item, always distinct.", + " C distinct Always empty thus no items to work with.", + " MS distinctUntilChanged At most one item, always distinct.", + " C distinctUntilChanged Always empty thus no items to work with.", + " MS doAfterNext Different terminology. Use [`doAfterSuccess()`](#doAfterSuccess).", + " C doAfterNext Always empty.", + "FO doAfterSuccess Different terminology. Use [`doAfterNext()`](#doAfterNext).", + " C doAfterSuccess Always empty thus no items to work with.", + " OMSC doOnCancel Different terminology. Use [`doOnDispose()`](#doOnDispose).", + " S doOnComplete Always succeeds or fails, there is no `onComplete` signal.", + "F doOnDispose Different terminology. Use [`doOnCancel()`](#doOnCancel).", + " MS doOnEach At most one item. Use [`doOnEvent()`](#doOnEvent).", + " C doOnEach Always empty thus no items to work with.", + "FO doOnEvent Use [`doOnEach()`](#doOnEach).", + " MS doOnNext Different terminology. Use [`doOnSuccess()`](#doOnSuccess).", + " C doOnNext Always empty thus no items to work with.", + " OMSC doOnRequest Backpressure related and not supported outside `Flowable`.", + "FO doOnSuccess Different terminology. Use [`doOnNext()`](#doOnNext).", + " C doOnSuccess Always empty thus no items to work with.", + " M elementAt At most one item with index 0. Use [`defaultIfEmpty`](#defaultIfEmpty).", + " S elementAt Always one item with index 0.", + " C elementAt Always empty thus no items to work with.", + " M elementAtOrError At most one item with index 0. Use [`toSingle`](#toSingle).", + " S empty Never empty.", + " C empty Use [`complete()`](#complete).", + " C filter Always empty thus no items to work with.", + " M first At most one item. Use [`defaultIfEmpty`](#defaultIfEmpty).", + " S first Always one item.", + " C first Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.", + " M firstElement At most one item, would be no-op.", + " S firstElement Always one item, would be no-op.", + " C firstElement Always empty.", + " M firstOrError At most one item, would be no-op.", + " S firstOrError Always one item, would be no-op.", + " C firstOrError Always empty. Use [`andThen()`](#andThen) and [`error()`](#error).", + " MS firstOrErrorStage At most one item. Use [`toCompletionStage()`](#toCompletionStage).", + " C firstOrErrorStage Always empty. Use [`andThen()`](#andThen), [`error()`](#error) and [`toCompletionStage()`](#toCompletionStage).", + " MSC firstStage At most one item. Use [`toCompletionStage()`](#toCompletionStage).", + " C flatMap Always empty thus no items to map.", + " C flatMapCompletable Always empty thus no items to map.", + " C flatMapCompletableDelayError Always empty thus no items to map.", + " C flatMapIterable Always empty thus no items to map.", + " C flatMapMaybe Always empty thus no items to map.", + " C flatMapMaybeDelayError Always empty thus no items to map.", + " C flatMapSingle Always empty thus no items to map.", + " C flatMapSingleDelayError Always empty thus no items to map.", + " C flatMapStream Always empty thus no items to map.", + " MS flatMapIterable At most one item. Use [`flattenAsFlowable`](#flattenAsFlowable) or [`flattenAsObservable`](#flattenAsObservable).", + " MS flatMapStream At most one item. Use [`flattenStreamAsFlowable`](#flattenStreamAsFlowable) or [`flattenStreamAsObservable`](#flattenStreamAsObservable).", + "F flatMapObservable Not supported. Use [`flatMap`](#flatMap) and [`toFlowable()`](#toFlowable).", + " O flatMapObservable Use [`flatMap`](#flatMap).", + " C flatMapObservable Always empty thus no items to map.", + " O flatMapPublisher Not supported. Use [`flatMap`](#flatMap) and [`toObservable()`](#toFlowable).", + "F flatMapPublisher Use [`flatMap`](#flatMap).", + " C flatMapPublisher Always empty thus no items to map.", + "FO flatMapSingleElement Use [`flatMapSingle`](#flatMapSingle).", + " S flatMapSingleElement Use [`flatMap`](#flatMap).", + " C flatMapSingleElement Always empty thus no items to map.", + "FO flattenAsFlowable Use [`flatMapIterable()`](#flatMapIterable).", + " C flattenAsFlowable Always empty thus no items to map.", + "FO flattenAsObservable Use [`flatMapIterable()`](#flatMapIterable).", + " C flattenAsObservable Always empty thus no items to map.", + "FO flattenStreamAsFlowable Use [`flatMapStream()`](#flatMapStream).", + " C flattenStreamAsFlowable Always empty thus no items to map.", + "FO flattenStreamAsObservable Use [`flatMapStream()`](#flatMapStream).", + " C flattenStreamAsObservable Always empty thus no items to map.", + " MSC forEach Use [`subscribe()`](#subscribe).", + " MSC forEachWhile Use [`subscribe()`](#subscribe).", + " M fromArray At most one item. Use [`just()`](#just) or [`empty()`](#empty).", + " S fromArray Always one item. Use [`just()`](#just).", + " C fromArray Always empty. Use [`complete()`](#complete).", + " S fromCompletable Always error.", + " C fromCompletable Use [`wrap()`](#wrap).", + " M fromIterable At most one item. Use [`just()`](#just) or [`empty()`](#empty).", + " S fromIterable Always one item. Use [`just()`](#just).", + " C fromIterable Always empty. Use [`complete()`](#complete).", + " M fromMaybe Use [`wrap()`](#wrap).", + " O fromObservable Use [`wrap()`](#wrap).", + " S fromOptional Always one item. Use [`just()`](#just).", + " C fromOptional Always empty. Use [`complete()`](#complete).", + " M fromStream At most one item. Use [`just()`](#just) or [`empty()`](#empty).", + " S fromStream Always one item. Use [`just()`](#just).", + " C fromStream Always empty. Use [`complete()`](#complete).", + " MSC generate Use [`fromSupplier()`](#fromSupplier).", + " MS groupBy At most one item.", + " C groupBy Always empty thus no items to group.", + " MS groupJoin At most one item.", + " C groupJoin Always empty thus no items to join.", + "FO ignoreElement Use [`ignoreElements()`](#ignoreElements).", + " C ignoreElement Always empty.", + " MS ignoreElements Use [`ignoreElement()`](#ignoreElement).", + " C ignoreElements Always empty.", + " MSC interval At most one item. Use [`timer()`](#timer).", + " MSC intervalRange At most one item. Use [`timer()`](#timer).", + " S isEmpty Always one item.", + " C isEmpty Always empty.", + " MS join At most one item. Use [`zip()`](#zip)", + " C join Always empty thus no items to join.", + " M last At most one item. Use [`defaultIfEmpty`](#defaultIfEmpty).", + " S last Always one item.", + " C last Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.", + " M lastElement At most one item, would be no-op.", + " S lastElement Always one item, would be no-op.", + " C lastElement Always empty.", + " M lastOrError At most one item, would be no-op.", + " S lastOrError Always one item, would be no-op.", + " C lastOrError Always empty. Use [`andThen()`](#andThen) and [`error()`](#error).", + " MS lastOrErrorStage At most one item. Use [`toCompletionStage()`](#toCompletionStage).", + " C lastOrErrorStage Always empty. Use [`andThen()`](#andThen), [`error()`](#error) and [`toCompletionStage()`](#toCompletionStage).", + " MSC lastStage At most one item. Use [`toCompletionStage()`](#toCompletionStage).", + " C map Always empty thus no items to map.", + " C mapOptional Always empty thus no items to map.", + " C ofType Always empty thus no items to filter.", + " OMSC onBackpressureBuffer Backpressure related and not supported outside `Flowable`.", + " OMSC onBackpressureDrop Backpressure related and not supported outside `Flowable`.", + " OMSC onBackpressureLatest Backpressure related and not supported outside `Flowable`.", + " OMSC parallel Needs backpressure thus not supported outside `Flowable`.", + " M publish Connectable sources not supported outside `Flowable` and `Observable`. Use a `MaybeSubject`.", + " S publish Connectable sources not supported outside `Flowable` and `Observable`. Use a `SingleSubject`.", + " C publish Connectable sources not supported outside `Flowable` and `Observable`. Use a `ConnectableSubject`.", + " MS range At most one item. Use [`just()`](#just).", + " C range Always empty. Use [`complete()`](#complete).", + " MS rangeLong At most one item. Use [`just()`](#just).", + " C rangeLong Always empty. Use [`complete()`](#complete).", + " OMSC rebatchRequests Backpressure related and not supported outside `Flowable`.", + " MS reduce At most one item. Use [`map()`](#map).", + " C reduce Always empty thus no items to reduce.", + " MS reduceWith At most one item. Use [`map()`](#map).", + " C reduceWith Always empty thus no items to reduce.", + " M replay Connectable sources not supported outside `Flowable` and `Observable`. Use a `MaybeSubject`.", + " S replay Connectable sources not supported outside `Flowable` and `Observable`. Use a `SingleSubject`.", + " C replay Connectable sources not supported outside `Flowable` and `Observable`. Use a `ConnectableSubject`.", + " MS sample At most one item, would be no-op.", + " C sample Always empty thus no items to work with.", + " MS scan At most one item. Use [`map()`](#map).", + " C scan Always empty thus no items to reduce.", + " MS scanWith At most one item. Use [`map()`](#map).", + " C scanWith Always empty thus no items to reduce.", + " MSC serialize At most one signal type.", + " M share Connectable sources not supported outside `Flowable` and `Observable`. Use a `MaybeSubject`.", + " S share Connectable sources not supported outside `Flowable` and `Observable`. Use a `SingleSubject`.", + " C share Connectable sources not supported outside `Flowable` and `Observable`. Use a `ConnectableSubject`.", + " M single At most one item. Use [`defaultIfEmpty`](#defaultIfEmpty).", + " S single Always one item.", + " C single Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.", + " M singleElement At most one item, would be no-op.", + " S singleElement Always one item, would be no-op.", + " C singleElement Always empty.", + " M singleOrError At most one item, would be no-op.", + " S singleOrError Always one item, would be no-op.", + " C singleOrError Always empty. Use [`andThen()`](#andThen) and [`error()`](#error).", + " MS singleOrErrorStage At most one item. Use [`toCompletionStage()`](#toCompletionStage).", + " C singleOrErrorStage Always empty. Use [`andThen()`](#andThen), [`error()`](#error) and [`toCompletionStage()`](#toCompletionStage).", + " MSC singleStage At most one item. Use [`toCompletionStage()`](#toCompletionStage).", + " MSC skip At most one item, would be no-op.", + " MSC skipLast At most one item, would be no-op.", + " MS skipWhile At most one item. Use [`filter()`](#filter).", + " C skipWhile Always empty.", + " MSC skipUntil At most one item. Use [`takeUntil()`](#takeUntil).", + " MSC sorted At most one item.", + " MSC startWithArray Use [`startWith()`](#startWith) and [`fromArray()`](#fromArray) of `Flowable` or `Observable`.", + " MSC startWithItem Use [`startWith()`](#startWith) and [`just()`](#just) of another reactive type.", + " MSC startWithIterable Use [`startWith()`](#startWith) and [`fromIterable()`](#fromArray) of `Flowable` or `Observable`.", + " S switchIfEmpty Never empty.", + " C switchIfEmpty Always empty. Use [`defaultIfEmpty()`](#defaultIfEmpty).", + " MS switchMap At most one item. Use [`flatMap()`](#flatMap).", + " C switchMap Always empty thus no items to map.", + " MS switchMapDelayError At most one item. Use [`flatMap()`](#flatMap).", + " C switchMapDelayError Always empty thus no items to map.", + " MS switchMapCompletable At most one item. Use [`flatMap()`](#flatMap).", + " C switchMapCompletable Always empty thus no items to map.", + " MS switchMapCompletableDelayError At most one item. Use [`flatMap()`](#flatMap).", + " C switchMapCompletableDelayError Always empty thus no items to map.", + " MS switchMapMaybe At most one item. Use [`flatMap()`](#flatMap).", + " C switchMapMaybe Always empty thus no items to map.", + " MS switchMapMaybeDelayError At most one item. Use [`flatMap()`](#flatMap).", + " C switchMapMaybeDelayError Always empty thus no items to map.", + " MS switchMapSingle At most one item. Use [`flatMap()`](#flatMap).", + " C switchMapSingle Always empty thus no items to map.", + " MS switchMapSingleDelayError At most one item. Use [`flatMap()`](#flatMap).", + " C switchMapSingleDelayError Always empty thus no items to map.", + " MSC take At most one item, would be no-op.", + " MSC takeLast At most one item, would be no-op.", + " MS takeWhile At most one item. Use [`filter()`](#filter).", + " C takeWhile Always empty.", + " MS throttleFirst At most one item signaled so no subsequent items to work with.", + " C throttleFirst Always empty thus no items to work with.", + " MS throttleLast At most one item signaled so no subsequent items to work with.", + " C throttleLast Always empty thus no items to work with.", + " MS throttleLatest At most one item signaled so no subsequent items to work with.", + " C throttleLatest Always empty thus no items to work with.", + " MS throttleWithTimeout At most one item signaled so no subsequent items to work with.", + " C throttleWithTimeout Always empty thus no items to work with.", + " C timestamp Always empty thus no items to work with.", + "FO toCompletionStage Use [`firstStage`](#firstStage), [`lastStage`](#lastStage) or [`singleStage`](#singleStage).", + " M toList At most one element to collect. Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a list/collection.", + " S toList One element to collect. Use [`map()`](#map) to transform into a list/collection.", + " C toList Always empty. Use [`andThen()`](#andThen) to bring in a collection.", + " M toMap At most one element to collect. Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a list/collection.", + " S toMap One element to collect. Use [`map()`](#map) to transform into a list/collection.", + " C toMap Always empty. Use [`andThen()`](#andThen) to bring in a collection.", + " M toMultimap At most one element to collect. Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a list/collection.", + " S toMultimap One element to collect. Use [`map()`](#map) to transform into a list/collection.", + " C toMultimap Always empty. Use [`andThen()`](#andThen) to bring in a collection.", + "FO toMaybe Use [`firstElement`](#firstElement), [`lastElement`](#lastElement) or [`singleElement`](#singleElement).", + " M toMaybe Would be no-op.", + " O toObservable Would be no-op.", + "FO toSingle Use [`firstOrError`](#firstOrError), [`lastOrError`](#lastOrError) or [`singleOrError`](#singleOrError).", + " S toSingle Would be no-op.", + "FO toSingleDefault Use [`first`](#first), [`last`](#last) or [`single`](#single).", + " M toSingleDefault Use [`defaultIfEmpty()`](#defaultIfEmpty).", + " S toSingleDefault Would be no-op.", + " M toSortedList At most one element to collect. Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a list/collection.", + " S toSortedList One element to collect. Use [`map()`](#map) to transform into a list/collection.", + " C toSortedList Always empty. Use [`andThen()`](#andThen) to bring in a collection.", + " M window Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a nested source.", + " S window Use [`map()`](#map) to transform into a nested source.", + " C window Always empty. Use [`andThen()`](#andThen) to bring in a nested source.", + " MS withLatestFrom At most one element per source. Use [`zip()`](#zip).", + " C withLatestFrom Always empty. Use [`merge()`](#merge).", + "F wrap Use [`fromPublisher()`](#fromPublisher).", + " C zip Use [`merge()`](#merge).", + " C zipArray Use [`mergeArray()`](#mergeArray).", + " C zipWith Use [`mergeWith()`](#mergeWith).", + }; + + static final Map> NOTES_MAP; + static { + NOTES_MAP = new HashMap<>(); + for (String s : NOTES) { + char[] classes = s.substring(0, 5).trim().toCharArray(); + int idx = s.indexOf(' ', 7); + String method = s.substring(6, idx); + String note = s.substring(idx).trim(); + + for (char c : classes) { + NOTES_MAP.computeIfAbsent(method, v -> new HashMap<>()) + .put(String.valueOf(c), note); + } } } } From e8d59c52c5c5391a668f33c6128f27766d8d79b3 Mon Sep 17 00:00:00 2001 From: akarnokd Date: Wed, 22 Jan 2020 14:22:11 +0100 Subject: [PATCH 05/37] Minor fix to the operator matrix. --- docs/Operator-Matrix.md | 17 ++++++++--------- .../internal/util/OperatorMatrixGenerator.java | 1 + 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/Operator-Matrix.md b/docs/Operator-Matrix.md index 832d64311d..3c3ef2c765 100644 --- a/docs/Operator-Matrix.md +++ b/docs/Operator-Matrix.md @@ -80,7 +80,6 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `elementAt`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| `elementAtOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| `empty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))| -`equals`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| `error`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `filter`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| `first`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))| @@ -173,7 +172,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| `scan`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))| `scanWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))| -`sequenceEqual`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`sequenceEqual`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| `serialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))| `share`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))| `single`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))| @@ -219,15 +218,15 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| `to`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toCompletionStage`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| `toList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| `toMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| -`toMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toMultimap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| -`toObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toSingleDefault`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toSingleDefault`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toSortedList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| `unsafeCreate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `unsubscribeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -333,8 +332,8 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat 91 Always empty. Use [`defaultIfEmpty()`](#defaultIfEmpty).
92 At most one item. Use [`flatMap()`](#flatMap).
93 Use [`firstStage`](#firstStage), [`lastStage`](#lastStage) or [`singleStage`](#singleStage).
-94 Use [`firstElement`](#firstElement), [`lastElement`](#lastElement) or [`singleElement`](#singleElement).
-95 Would be no-op.
+94 Would be no-op.
+95 Use [`firstElement`](#firstElement), [`lastElement`](#lastElement) or [`singleElement`](#singleElement).
96 Use [`firstOrError`](#firstOrError), [`lastOrError`](#lastOrError) or [`singleOrError`](#singleOrError).
97 Use [`first`](#first), [`last`](#last) or [`single`](#single).
98 Use [`defaultIfEmpty()`](#defaultIfEmpty).
diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java index 1273a5b441..970d6e36bb 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java @@ -419,6 +419,7 @@ static String findNotes(String clazzName, String operatorName) { " C throttleWithTimeout Always empty thus no items to work with.", " C timestamp Always empty thus no items to work with.", "FO toCompletionStage Use [`firstStage`](#firstStage), [`lastStage`](#lastStage) or [`singleStage`](#singleStage).", + "F toFlowable Would be no-op.", " M toList At most one element to collect. Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a list/collection.", " S toList One element to collect. Use [`map()`](#map) to transform into a list/collection.", " C toList Always empty. Use [`andThen()`](#andThen) to bring in a collection.", From 5dbc2a84f970bf0bb8670bec13ab2aa836ebad66 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Wed, 22 Jan 2020 17:37:14 +0100 Subject: [PATCH 06/37] 3.x: Add last missing throws tag to JavaDocs (#6860) --- .../io/reactivex/rxjava3/core/Flowable.java | 7 +- .../io/reactivex/rxjava3/core/Single.java | 1 + .../internal/util/JavadocNoThrows.java | 72 +++++++++++++++++++ .../validators/ParamValidationNaming.java | 3 + 4 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/util/JavadocNoThrows.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Flowable.java b/src/main/java/io/reactivex/rxjava3/core/Flowable.java index 5f5aff68c6..0106f42ce9 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Flowable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Flowable.java @@ -213,7 +213,7 @@ public static Flowable amb(@NonNull Iterable<@NonNull ? extends Publisher @BackpressureSupport(BackpressureKind.PASS_THROUGH) @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs - public static Flowable ambArray(Publisher<@NonNull ? extends T>... sources) { + public static Flowable ambArray(@NonNull Publisher<@NonNull ? extends T>... sources) { Objects.requireNonNull(sources, "sources is null"); int len = sources.length; if (len == 0) { @@ -1915,7 +1915,7 @@ public static Flowable empty() { * @param supplier * a {@link Supplier} factory to return a {@link Throwable} for each individual {@code Subscriber} * @param - * the type of the items (ostensibly) emitted by the {@link Publisher} + * the type of the items (ostensibly) emitted by the resulting {@code Flowable} * @return the new {@code Flowable} instance * @throws NullPointerException if {@code supplier} is {@code null} * @see ReactiveX operators documentation: Throw @@ -1944,7 +1944,7 @@ public static Flowable error(@NonNull Supplier suppl * @param throwable * the particular {@link Throwable} to pass to {@link Subscriber#onError onError} * @param - * the type of the items (ostensibly) emitted by the {@link Publisher} + * the type of the items (ostensibly) emitted by the resulting {@code Flowable} * @return the new {@code Flowable} instance * @throws NullPointerException if {@code throwable} is {@code null} * @see ReactiveX operators documentation: Throw @@ -8760,6 +8760,7 @@ public final Flowable delay(long time, @NonNull TimeUnit unit, @NonNull Sched * then used to delay the emission of that item by the resulting {@code Flowable} until the {@code Publisher} * returned from {@code itemDelay} emits an item * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code subscriptionIndicator} and {@code itemDelayIndicator} is {@code null} * @see ReactiveX operators documentation: Delay */ @CheckReturnValue diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index f915bdc5b2..c93bfa9282 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -681,6 +681,7 @@ public static Single error(@NonNull Throwable throwable) { * the type of object that the {@code Future} returns, and also the type of item to be emitted by * the resulting {@code Single} * @return the new {@code Single} that emits the item from the source {@code Future} + * @throws NullPointerException if {@code future} is {@code null} * @see ReactiveX operators documentation: From * @see #fromFuture(Future, long, TimeUnit) * @see #fromCompletionStage(CompletionStage) diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/JavadocNoThrows.java b/src/test/java/io/reactivex/rxjava3/internal/util/JavadocNoThrows.java new file mode 100644 index 0000000000..985ac202c3 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/util/JavadocNoThrows.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ +package io.reactivex.rxjava3.internal.util; + +import java.io.File; +import java.nio.file.Files; +import java.util.List; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.parallel.ParallelFlowable; +import io.reactivex.rxjava3.testsupport.TestHelper; + +/** + * Scan the JavaDocs of the base classes and list those which do not have the {@code @throws} tag. + * The lack is not an error by itself but worth looking at. + */ +public final class JavadocNoThrows { + + private JavadocNoThrows() { + throw new IllegalArgumentException("No instances!"); + } + + public static void main(String[] args) throws Exception { + for (Class clazz : CLASSES) { + String clazzName = clazz.getSimpleName(); + String packageName = clazz.getPackage().getName(); + File f = TestHelper.findSource(clazzName, packageName); + + List lines = Files.readAllLines(f.toPath()); + + for (int i = 1; i < lines.size(); i++) { + String line = lines.get(i).trim(); + + if (line.startsWith("/**")) { + boolean found = false; + for (int j = i + 1; j < lines.size(); j++) { + + String line2 = lines.get(j).trim(); + if (line2.startsWith("public")) { + if (line2.endsWith("() {")) { + found = true; + } + break; + } + if (line2.startsWith("* @throws")) { + found = true; + break; + } + } + + if (!found) { + System.out.printf(" at %s.%s.method(%s.java:%s)%n%n", packageName, clazzName, clazzName, i + 1); + } + } + } + } + } + + static final Class[] CLASSES = { + Flowable.class, Observable.class, Maybe.class, Single.class, Completable.class, ParallelFlowable.class + }; +} diff --git a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java index ba307d394d..2ce716e342 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java +++ b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java @@ -523,6 +523,9 @@ static final class ValidatorStrings { new ValidatorStrings("stage", "* @throws NullPointerException"), new ValidatorStrings("stream", "* @throws NullPointerException"), new ValidatorStrings("collector", "* @throws NullPointerException"), + new ValidatorStrings("subscriptionIndicator", "* @throws NullPointerException"), + new ValidatorStrings("itemDelayIndicator", "* @throws NullPointerException"), + new ValidatorStrings("future", "* @throws NullPointerException"), new ValidatorStrings("parallelism", "* @throws IllegalArgumentException"), new ValidatorStrings("prefetch", "* @throws IllegalArgumentException"), From 49f1a6d0f0540d6b98e2c11d70ad54ff0c4bc18f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2020 09:50:48 +0100 Subject: [PATCH 07/37] Bump biz.aQute.bnd.gradle from 4.3.1 to 5.0.0 (#6861) Bumps [biz.aQute.bnd.gradle](https://github.com/bndtools/bnd) from 4.3.1 to 5.0.0. - [Release notes](https://github.com/bndtools/bnd/releases) - [Changelog](https://github.com/bndtools/bnd/blob/master/docs/ADDING_RELEASE_DOCS.md) - [Commits](https://github.com/bndtools/bnd/commits) Signed-off-by: dependabot-preview[bot] --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ce041a954f..b0a12f1c79 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ buildscript { ext.licenseVersion = "0.15.0" ext.bintrayVersion = "1.8.4" ext.jfrogExtractorVersion = "4.13.0" - ext.bndVersion = "4.3.1" + ext.bndVersion = "5.0.0" ext.checkstyleVersion = "8.26" // -------------------------------------- From bb3260ec3729d9d9c0934a958f3added8ca65408 Mon Sep 17 00:00:00 2001 From: Paul Estrada <2215585+pestrada@users.noreply.github.com> Date: Fri, 24 Jan 2020 01:41:40 -0600 Subject: [PATCH 08/37] add delayError to Maybe.delay (#6864) --- .../java/io/reactivex/rxjava3/core/Maybe.java | 65 +++++++++++++++++-- .../internal/operators/maybe/MaybeDelay.java | 20 ++++-- .../operators/maybe/MaybeDelayTest.java | 28 ++++++++ .../ParamValidationCheckerTest.java | 2 + 4 files changed, 102 insertions(+), 13 deletions(-) diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 4322afaa93..6260f3e206 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -2672,6 +2672,7 @@ public final Single defaultIfEmpty(@NonNull T defaultItem) { /** * Returns a {@code Maybe} that signals the events emitted by the current {@code Maybe} shifted forward in time by a * specified delay. + * An error signal will not be delayed. *

* *

@@ -2682,17 +2683,68 @@ public final Single defaultIfEmpty(@NonNull T defaultItem) { * @param time * the delay to shift the source by * @param unit - * the {@link TimeUnit} in which {@code period} is defined + * the {@link TimeUnit} in which {@code time} is defined * @return the new {@code Maybe} instance * @throws NullPointerException if {@code unit} is {@code null} * @see ReactiveX operators documentation: Delay - * @see #delay(long, TimeUnit, Scheduler) + * @see #delay(long, TimeUnit, Scheduler, boolean) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.COMPUTATION) @NonNull public final Maybe delay(long time, @NonNull TimeUnit unit) { - return delay(time, unit, Schedulers.computation()); + return delay(time, unit, Schedulers.computation(), false); + } + + /** + * Returns a {@code Maybe} that signals the events emitted by the current {@code Maybe} shifted forward in time by a + * specified delay. + *

+ * + *

+ *
Scheduler:
+ *
This version of {@code delay} operates by default on the {@code computation} {@link Scheduler}.
+ *
+ * + * @param time the delay to shift the source by + * @param unit the {@link TimeUnit} in which {@code time} is defined + * @param delayError if {@code true}, both success and error signals are delayed. if {@code false}, only success signals are delayed. + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code unit} is {@code null} + * @see ReactiveX operators documentation: Delay + * @see #delay(long, TimeUnit, Scheduler, boolean) + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.COMPUTATION) + @NonNull + public final Maybe delay(long time, @NonNull TimeUnit unit, boolean delayError) { + return delay(time, unit, Schedulers.computation(), delayError); + } + + /** + * Returns a {@code Maybe} that signals the events emitted by the current {@code Maybe} shifted forward in time by a + * specified delay. + * An error signal will not be delayed. + *

+ * + *

+ *
Scheduler:
+ *
you specify the {@link Scheduler} where the non-blocking wait and emission happens
+ *
+ * + * @param time the delay to shift the source by + * @param unit the {@link TimeUnit} in which {@code time} is defined + * @param scheduler the {@code Scheduler} to use for delaying + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} + * @see ReactiveX operators documentation: Delay + * @see #delay(long, TimeUnit, Scheduler, boolean) + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.CUSTOM) + @NonNull + public final Maybe delay(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + return delay(time, unit, scheduler, false); } /** @@ -2708,9 +2760,10 @@ public final Maybe delay(long time, @NonNull TimeUnit unit) { * @param time * the delay to shift the source by * @param unit - * the time unit of {@code delay} + * the {@link TimeUnit} in which {@code time} is defined * @param scheduler * the {@code Scheduler} to use for delaying + * @param delayError if {@code true}, both success and error signals are delayed. if {@code false}, only success signals are delayed. * @return the new {@code Maybe} instance * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} * @see ReactiveX operators documentation: Delay @@ -2718,10 +2771,10 @@ public final Maybe delay(long time, @NonNull TimeUnit unit) { @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.CUSTOM) - public final Maybe delay(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + public final Maybe delay(long time, @NonNull TimeUnit unit, @NonNull Scheduler scheduler, boolean delayError) { Objects.requireNonNull(unit, "unit is null"); Objects.requireNonNull(scheduler, "scheduler is null"); - return RxJavaPlugins.onAssembly(new MaybeDelay<>(this, Math.max(0L, time), unit, scheduler)); + return RxJavaPlugins.onAssembly(new MaybeDelay<>(this, Math.max(0L, time), unit, scheduler, delayError)); } /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelay.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelay.java index 6885763cbd..3e6922a339 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelay.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelay.java @@ -33,16 +33,19 @@ public final class MaybeDelay extends AbstractMaybeWithUpstream { final Scheduler scheduler; - public MaybeDelay(MaybeSource source, long delay, TimeUnit unit, Scheduler scheduler) { + final boolean delayError; + + public MaybeDelay(MaybeSource source, long delay, TimeUnit unit, Scheduler scheduler, boolean delayError) { super(source); this.delay = delay; this.unit = unit; this.scheduler = scheduler; + this.delayError = delayError; } @Override protected void subscribeActual(MaybeObserver observer) { - source.subscribe(new DelayMaybeObserver<>(observer, delay, unit, scheduler)); + source.subscribe(new DelayMaybeObserver<>(observer, delay, unit, scheduler, delayError)); } static final class DelayMaybeObserver @@ -59,15 +62,18 @@ static final class DelayMaybeObserver final Scheduler scheduler; + final boolean delayError; + T value; Throwable error; - DelayMaybeObserver(MaybeObserver actual, long delay, TimeUnit unit, Scheduler scheduler) { + DelayMaybeObserver(MaybeObserver actual, long delay, TimeUnit unit, Scheduler scheduler, boolean delayError) { this.downstream = actual; this.delay = delay; this.unit = unit; this.scheduler = scheduler; + this.delayError = delayError; } @Override @@ -105,21 +111,21 @@ public void onSubscribe(Disposable d) { @Override public void onSuccess(T value) { this.value = value; - schedule(); + schedule(delay); } @Override public void onError(Throwable e) { this.error = e; - schedule(); + schedule(delayError ? delay : 0); } @Override public void onComplete() { - schedule(); + schedule(delay); } - void schedule() { + void schedule(long delay) { DisposableHelper.replace(this, scheduler.scheduleDirect(this, delay, unit)); } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayTest.java index 747b96faf1..14448c3f2c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDelayTest.java @@ -96,4 +96,32 @@ public Maybe apply(Maybe f) throws Exception { } }); } + + @Test + public void delayedErrorOnSuccess() { + final TestScheduler scheduler = new TestScheduler(); + final TestObserver observer = Maybe.just(1) + .delay(5, TimeUnit.SECONDS, scheduler, true) + .test(); + + scheduler.advanceTimeTo(2, TimeUnit.SECONDS); + observer.assertNoValues(); + + scheduler.advanceTimeTo(5, TimeUnit.SECONDS); + observer.assertValue(1); + } + + @Test + public void delayedErrorOnError() { + final TestScheduler scheduler = new TestScheduler(); + final TestObserver observer = Maybe.error(new TestException()) + .delay(5, TimeUnit.SECONDS, scheduler, true) + .test(); + + scheduler.advanceTimeTo(2, TimeUnit.SECONDS); + observer.assertNoErrors(); + + scheduler.advanceTimeTo(5, TimeUnit.SECONDS); + observer.assertError(TestException.class); + } } diff --git a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java index 403a83964a..7eff55d15e 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java +++ b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationCheckerTest.java @@ -289,6 +289,8 @@ public void checkParallelFlowable() { // negative time is considered as zero time addOverride(new ParamOverride(Maybe.class, 0, ParamMode.ANY, "delay", Long.TYPE, TimeUnit.class)); addOverride(new ParamOverride(Maybe.class, 0, ParamMode.ANY, "delay", Long.TYPE, TimeUnit.class, Scheduler.class)); + addOverride(new ParamOverride(Maybe.class, 0, ParamMode.ANY, "delay", Long.TYPE, TimeUnit.class, Boolean.TYPE)); + addOverride(new ParamOverride(Maybe.class, 0, ParamMode.ANY, "delay", Long.TYPE, TimeUnit.class, Scheduler.class, Boolean.TYPE)); // zero repeat is allowed addOverride(new ParamOverride(Maybe.class, 0, ParamMode.NON_NEGATIVE, "repeat", Long.TYPE)); From 33a1dcfab98463d41d5b1502e66fa82b6d9ae3c6 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Fri, 24 Jan 2020 17:35:55 +0100 Subject: [PATCH 09/37] 3.x: Add Maybe/Single/Completable blockingSubscribe (#6862) * 3.x: Add Maybe/Single/Completable blockingSubscribe * Update marble dimensions --- .../reactivex/rxjava3/core/Completable.java | 100 ++++ .../java/io/reactivex/rxjava3/core/Maybe.java | 131 ++++- .../io/reactivex/rxjava3/core/Single.java | 100 ++++ .../BlockingDisposableMultiObserver.java | 154 ++++++ .../observers/BlockingMultiObserver.java | 38 ++ .../CompletableBlockingSubscribeTest.java | 331 ++++++++++++ .../maybe/MaybeBlockingSubscribeTest.java | 502 ++++++++++++++++++ .../single/SingleBlockingSubscribeTest.java | 343 ++++++++++++ 8 files changed, 1698 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/observers/BlockingDisposableMultiObserver.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableBlockingSubscribeTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeBlockingSubscribeTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleBlockingSubscribeTest.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 1266255315..0913ac398d 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -1310,6 +1310,106 @@ public final boolean blockingAwait(long timeout, @NonNull TimeUnit unit) { return observer.blockingAwait(timeout, unit); } + /** + * Subscribes to the current {@code Completable} and blocks the current thread until it terminates. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If the current {@code Completable} signals an error, + * the {@link Throwable} is routed to the global error handler via {@link RxJavaPlugins#onError(Throwable)}. + * If the current thread is interrupted, an {@link InterruptedException} is routed to the same global error handler. + *
+ *
+ * @since 3.0.0 + * @see #blockingSubscribe(Action) + * @see #blockingSubscribe(Action, Consumer) + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe() { + blockingSubscribe(Functions.EMPTY_ACTION, Functions.ERROR_CONSUMER); + } + + /** + * Subscribes to the current {@code Completable} and calls given {@code onComplete} callback on the current thread + * when it completes normally. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If either the current {@code Completable} signals an error or {@code onComplete} throws, + * the respective {@link Throwable} is routed to the global error handler via {@link RxJavaPlugins#onError(Throwable)}. + * If the current thread is interrupted, an {@link InterruptedException} is routed to the same global error handler. + *
+ *
+ * @param onComplete the {@link Action} to call if the current {@code Completable} completes normally + * @throws NullPointerException if {@code onComplete} is {@code null} + * @since 3.0.0 + * @see #blockingSubscribe(Action, Consumer) + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe(@NonNull Action onComplete) { + blockingSubscribe(onComplete, Functions.ERROR_CONSUMER); + } + + /** + * Subscribes to the current {@code Completable} and calls the appropriate callback on the current thread + * when it terminates. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If either {@code onComplete} or {@code onError} throw, the {@link Throwable} is routed to the + * global error handler via {@link RxJavaPlugins#onError(Throwable)}. + * If the current thread is interrupted, the {@code onError} consumer is called with an {@link InterruptedException}. + *
+ *
+ * @param onComplete the {@link Action} to call if the current {@code Completable} completes normally + * @param onError the {@link Consumer} to call if the current {@code Completable} signals an error + * @throws NullPointerException if {@code onComplete} or {@code onError} is {@code null} + * @since 3.0.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe(@NonNull Action onComplete, @NonNull Consumer onError) { + Objects.requireNonNull(onComplete, "onComplete is null"); + Objects.requireNonNull(onError, "onError is null"); + BlockingMultiObserver observer = new BlockingMultiObserver<>(); + subscribe(observer); + observer.blockingConsume(Functions.emptyConsumer(), onError, onComplete); + } + + /** + * Subscribes to the current {@code Completable} and calls the appropriate {@link CompletableObserver} method on the current thread. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
An {@code onError} signal is delivered to the {@link CompletableObserver#onError(Throwable)} method. + * If any of the {@code CompletableObserver}'s methods throw, the {@link RuntimeException} is propagated to the caller of this method. + * If the current thread is interrupted, an {@link InterruptedException} is delivered to {@code observer.onError}. + *
+ *
+ * @param observer the {@code CompletableObserver} to call methods on the current thread + * @throws NullPointerException if {@code observer} is {@code null} + * @since 3.0.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe(@NonNull CompletableObserver observer) { + Objects.requireNonNull(observer, "observer is null"); + BlockingDisposableMultiObserver blockingObserver = new BlockingDisposableMultiObserver<>(); + observer.onSubscribe(blockingObserver); + subscribe(blockingObserver); + blockingObserver.blockingConsume(observer); + } + /** * Subscribes to this {@code Completable} only once, when the first {@link CompletableObserver} * subscribes to the result {@code Completable}, caches its terminal event diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 6260f3e206..0d0d6f5473 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -26,7 +26,7 @@ import io.reactivex.rxjava3.internal.functions.*; import io.reactivex.rxjava3.internal.fuseable.*; import io.reactivex.rxjava3.internal.jdk8.*; -import io.reactivex.rxjava3.internal.observers.BlockingMultiObserver; +import io.reactivex.rxjava3.internal.observers.*; import io.reactivex.rxjava3.internal.operators.flowable.*; import io.reactivex.rxjava3.internal.operators.maybe.*; import io.reactivex.rxjava3.internal.operators.mixed.*; @@ -2475,6 +2475,135 @@ public final T blockingGet(@NonNull T defaultValue) { return observer.blockingGet(defaultValue); } + /** + * Subscribes to the current {@code Maybe} and blocks the current thread until it terminates. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If the current {@code Maybe} signals an error, + * the {@link Throwable} is routed to the global error handler via {@link RxJavaPlugins#onError(Throwable)}. + * If the current thread is interrupted, an {@link InterruptedException} is routed to the same global error handler. + *
+ *
+ * @since 3.0.0 + * @see #blockingSubscribe(Consumer) + * @see #blockingSubscribe(Consumer, Consumer) + * @see #blockingSubscribe(Consumer, Consumer, Action) + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe() { + blockingSubscribe(Functions.emptyConsumer(), Functions.ERROR_CONSUMER, Functions.EMPTY_ACTION); + } + + /** + * Subscribes to the current {@code Maybe} and calls given {@code onSuccess} callback on the current thread + * when it completes normally. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If either the current {@code Maybe} signals an error or {@code onSuccess} throws, + * the respective {@link Throwable} is routed to the global error handler via {@link RxJavaPlugins#onError(Throwable)}. + * If the current thread is interrupted, an {@link InterruptedException} is routed to the same global error handler. + *
+ *
+ * @param onSuccess the {@link Consumer} to call if the current {@code Maybe} succeeds + * @throws NullPointerException if {@code onSuccess} is {@code null} + * @since 3.0.0 + * @see #blockingSubscribe(Consumer, Consumer) + * @see #blockingSubscribe(Consumer, Consumer, Action) + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe(@NonNull Consumer onSuccess) { + blockingSubscribe(onSuccess, Functions.ERROR_CONSUMER, Functions.EMPTY_ACTION); + } + + /** + * Subscribes to the current {@code Maybe} and calls the appropriate callback on the current thread + * when it terminates. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If either {@code onSuccess} or {@code onError} throw, the {@link Throwable} is routed to the + * global error handler via {@link RxJavaPlugins#onError(Throwable)}. + * If the current thread is interrupted, the {@code onError} consumer is called with an {@link InterruptedException}. + *
+ *
+ * @param onSuccess the {@link Consumer} to call if the current {@code Maybe} succeeds + * @param onError the {@code Consumer} to call if the current {@code Maybe} signals an error + * @throws NullPointerException if {@code onSuccess} or {@code onError} is {@code null} + * @since 3.0.0 + * @see #blockingSubscribe(Consumer, Consumer, Action) + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe(@NonNull Consumer onSuccess, @NonNull Consumer onError) { + blockingSubscribe(onSuccess, onError, Functions.EMPTY_ACTION); + } + + /** + * Subscribes to the current {@code Maybe} and calls the appropriate callback on the current thread + * when it terminates. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If either {@code onSuccess}, {@code onError} or {@code onComplete} throw, the {@link Throwable} is routed to the + * global error handler via {@link RxJavaPlugins#onError(Throwable)}. + * If the current thread is interrupted, the {@code onError} consumer is called with an {@link InterruptedException}. + *
+ *
+ * @param onSuccess the {@link Consumer} to call if the current {@code Maybe} succeeds + * @param onError the {@code Consumer} to call if the current {@code Maybe} signals an error + * @param onComplete the {@linnk Action} to call if the current {@code Maybe} completes without a value + * @throws NullPointerException if {@code onSuccess}, {@code onError} or {@code onComplete} is {@code null} + * @since 3.0.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe(@NonNull Consumer onSuccess, @NonNull Consumer onError, @NonNull Action onComplete) { + Objects.requireNonNull(onSuccess, "onSuccess is null"); + Objects.requireNonNull(onError, "onError is null"); + Objects.requireNonNull(onComplete, "onComplete is null"); + BlockingMultiObserver observer = new BlockingMultiObserver<>(); + subscribe(observer); + observer.blockingConsume(onSuccess, onError, onComplete); + } + + /** + * Subscribes to the current {@code Maybe} and calls the appropriate {@link MaybeObserver} method on the current thread. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
An {@code onError} signal is delivered to the {@link MaybeObserver#onError(Throwable)} method. + * If any of the {@code MaybeObserver}'s methods throw, the {@link RuntimeException} is propagated to the caller of this method. + * If the current thread is interrupted, an {@link InterruptedException} is delivered to {@code observer.onError}. + *
+ *
+ * @param observer the {@code MaybeObserver} to call methods on the current thread + * @throws NullPointerException if {@code observer} is {@code null} + * @since 3.0.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe(@NonNull MaybeObserver observer) { + Objects.requireNonNull(observer, "observer is null"); + BlockingDisposableMultiObserver blockingObserver = new BlockingDisposableMultiObserver<>(); + observer.onSubscribe(blockingObserver); + subscribe(blockingObserver); + blockingObserver.blockingConsume(observer); + } + /** * Returns a {@code Maybe} that subscribes to this {@code Maybe} lazily, caches its event * and replays it, to all the downstream subscribers. diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index c93bfa9282..216d3deb87 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -2947,6 +2947,106 @@ public final T blockingGet() { return observer.blockingGet(); } + /** + * Subscribes to the current {@code Single} and blocks the current thread until it terminates. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If the current {@code Single} signals an error, + * the {@link Throwable} is routed to the global error handler via {@link RxJavaPlugins#onError(Throwable)}. + * If the current thread is interrupted, an {@link InterruptedException} is routed to the same global error handler. + *
+ *
+ * @since 3.0.0 + * @see #blockingSubscribe(Consumer) + * @see #blockingSubscribe(Consumer, Consumer) + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe() { + blockingSubscribe(Functions.emptyConsumer(), Functions.ERROR_CONSUMER); + } + + /** + * Subscribes to the current {@code Single} and calls given {@code onSuccess} callback on the current thread + * when it completes normally. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If either the current {@code Single} signals an error or {@code onSuccess} throws, + * the respective {@link Throwable} is routed to the global error handler via {@link RxJavaPlugins#onError(Throwable)}. + * If the current thread is interrupted, an {@link InterruptedException} is routed to the same global error handler. + *
+ *
+ * @param onSuccess the {@link Consumer} to call if the current {@code Single} succeeds + * @throws NullPointerException if {@code onSuccess} is {@code null} + * @since 3.0.0 + * @see #blockingSubscribe(Consumer, Consumer) + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe(@NonNull Consumer onSuccess) { + blockingSubscribe(onSuccess, Functions.ERROR_CONSUMER); + } + + /** + * Subscribes to the current {@code Single} and calls the appropriate callback on the current thread + * when it terminates. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If either {@code onSuccess} or {@code onError} throw, the {@link Throwable} is routed to the + * global error handler via {@link RxJavaPlugins#onError(Throwable)}. + * If the current thread is interrupted, the {@code onError} consumer is called with an {@link InterruptedException}. + *
+ *
+ * @param onSuccess the {@link Consumer} to call if the current {@code Single} succeeds + * @param onError the {@code Consumer} to call if the current {@code Single} signals an error + * @throws NullPointerException if {@code onSuccess} or {@code onError} is {@code null} + * @since 3.0.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe(@NonNull Consumer onSuccess, @NonNull Consumer onError) { + Objects.requireNonNull(onSuccess, "onSuccess is null"); + Objects.requireNonNull(onError, "onError is null"); + BlockingMultiObserver observer = new BlockingMultiObserver<>(); + subscribe(observer); + observer.blockingConsume(onSuccess, onError, Functions.EMPTY_ACTION); + } + + /** + * Subscribes to the current {@code Single} and calls the appropriate {@link SingleObserver} method on the current thread. + *

+ * + *

+ *
Scheduler:
+ *
{@code blockingSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
An {@code onError} signal is delivered to the {@link SingleObserver#onError(Throwable)} method. + * If any of the {@code SingleObserver}'s methods throw, the {@link RuntimeException} is propagated to the caller of this method. + * If the current thread is interrupted, an {@link InterruptedException} is delivered to {@code observer.onError}. + *
+ *
+ * @param observer the {@code SingleObserver} to call methods on the current thread + * @throws NullPointerException if {@code observer} is {@code null} + * @since 3.0.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void blockingSubscribe(@NonNull SingleObserver observer) { + Objects.requireNonNull(observer, "observer is null"); + BlockingDisposableMultiObserver blockingObserver = new BlockingDisposableMultiObserver<>(); + observer.onSubscribe(blockingObserver); + subscribe(blockingObserver); + blockingObserver.blockingConsume(observer); + } + /** * This method requires advanced knowledge about building operators, please consider * other standard composition methods first; diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingDisposableMultiObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingDisposableMultiObserver.java new file mode 100644 index 0000000000..da7e289e27 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingDisposableMultiObserver.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import java.util.concurrent.CountDownLatch; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.internal.disposables.*; +import io.reactivex.rxjava3.internal.util.BlockingHelper; + +/** + * Blocks until the upstream terminates and dispatches the outcome to + * the actual observer. + * + * @param the element type of the source + * @since 3.0.0 + */ +public final class BlockingDisposableMultiObserver +extends CountDownLatch +implements MaybeObserver, SingleObserver, CompletableObserver, Disposable { + + T value; + Throwable error; + + final SequentialDisposable upstream; + + public BlockingDisposableMultiObserver() { + super(1); + upstream = new SequentialDisposable(); + } + + @Override + public void dispose() { + upstream.dispose(); + countDown(); + } + + @Override + public boolean isDisposed() { + return upstream.isDisposed(); + } + + @Override + public void onSubscribe(@NonNull Disposable d) { + DisposableHelper.setOnce(upstream, d); + } + + @Override + public void onSuccess(@NonNull T t) { + this.value = t; + upstream.lazySet(Disposable.disposed()); + countDown(); + } + + @Override + public void onError(@NonNull Throwable e) { + this.error = e; + upstream.lazySet(Disposable.disposed()); + countDown(); + } + + @Override + public void onComplete() { + upstream.lazySet(Disposable.disposed()); + countDown(); + } + + public void blockingConsume(CompletableObserver observer) { + if (getCount() != 0) { + try { + BlockingHelper.verifyNonBlocking(); + await(); + } catch (InterruptedException ex) { + dispose(); + observer.onError(ex); + return; + } + } + if (isDisposed()) { + return; + } + + Throwable ex = error; + if (ex != null) { + observer.onError(ex); + } else { + observer.onComplete(); + } + } + + public void blockingConsume(SingleObserver observer) { + if (getCount() != 0) { + try { + BlockingHelper.verifyNonBlocking(); + await(); + } catch (InterruptedException ex) { + dispose(); + observer.onError(ex); + return; + } + } + if (isDisposed()) { + return; + } + + Throwable ex = error; + if (ex != null) { + observer.onError(ex); + } else { + observer.onSuccess(value); + } + } + + public void blockingConsume(MaybeObserver observer) { + if (getCount() != 0) { + try { + BlockingHelper.verifyNonBlocking(); + await(); + } catch (InterruptedException ex) { + dispose(); + observer.onError(ex); + return; + } + } + if (isDisposed()) { + return; + } + + Throwable ex = error; + if (ex != null) { + observer.onError(ex); + } else { + T v = value; + if (v == null) { + observer.onComplete(); + } else { + observer.onSuccess(v); + } + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserver.java index 1f4ee305bd..4945730ab5 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/BlockingMultiObserver.java @@ -17,7 +17,10 @@ import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.util.*; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; /** * A combined Observer that awaits the success or error signal via a CountDownLatch. @@ -143,4 +146,39 @@ public boolean blockingAwait(long timeout, TimeUnit unit) { } return true; } + + /** + * Blocks until the source completes and calls the appropriate callback. + * @param onSuccess for a succeeding source + * @param onError for a failing source + * @param onComplete for an empty source + */ + public void blockingConsume(Consumer onSuccess, Consumer onError, Action onComplete) { + try { + if (getCount() != 0) { + try { + BlockingHelper.verifyNonBlocking(); + await(); + } catch (InterruptedException ex) { + dispose(); + onError.accept(ex); + return; + } + } + Throwable ex = error; + if (ex != null) { + onError.accept(ex); + return; + } + T v = value; + if (v != null) { + onSuccess.accept(v); + } else { + onComplete.run(); + } + } catch (Throwable t) { + Exceptions.throwIfFatal(t); + RxJavaPlugins.onError(t); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableBlockingSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableBlockingSubscribeTest.java new file mode 100644 index 0000000000..e70aac7157 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableBlockingSubscribeTest.java @@ -0,0 +1,331 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.completable; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class CompletableBlockingSubscribeTest { + + @Test + public void noArgComplete() { + Completable.complete() + .blockingSubscribe(); + } + + @Test + public void noArgCompleteAsync() { + Completable.complete() + .delay(100, TimeUnit.MILLISECONDS) + .blockingSubscribe(); + } + + @Test + public void noArgError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Completable.error(new TestException()) + .blockingSubscribe(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void noArgErrorAsync() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Completable.error(new TestException()) + .delay(100, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void oneArgComplete() throws Throwable { + Action action = mock(Action.class); + + Completable.complete() + .blockingSubscribe(action); + + verify(action).run(); + } + + @Test + public void oneArgCompleteAsync() throws Throwable { + Action action = mock(Action.class); + + Completable.complete() + .delay(50, TimeUnit.MILLISECONDS) + .blockingSubscribe(action); + + verify(action).run(); + } + + @Test + public void oneArgCompleteFails() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action action = mock(Action.class); + doThrow(new TestException()).when(action).run(); + + Completable.complete() + .blockingSubscribe(action); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(action).run(); + }); + } + + @Test + public void oneArgError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action action = mock(Action.class); + + Completable.error(new TestException()) + .blockingSubscribe(action); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(action, never()).run(); + }); + } + + @Test + public void oneArgErrorAsync() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action action = mock(Action.class); + + Completable.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(action); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(action, never()).run(); + }); + } + + @Test + public void twoArgComplete() throws Throwable { + Action action = mock(Action.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Completable.complete() + .blockingSubscribe(action, consumer); + + verify(action).run(); + verify(consumer, never()).accept(any()); + } + + @Test + public void twoArgCompleteAsync() throws Throwable { + Action action = mock(Action.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Completable.complete() + .delay(50, TimeUnit.MILLISECONDS) + .blockingSubscribe(action, consumer); + + verify(action).run(); + verify(consumer, never()).accept(any()); + } + + @Test + public void twoArgCompleteFails() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action action = mock(Action.class); + doThrow(new TestException()).when(action).run(); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Completable.complete() + .blockingSubscribe(action, consumer); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(action).run(); + verify(consumer, never()).accept(any()); + }); + } + + @Test + public void twoArgError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action action = mock(Action.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Completable.error(new TestException()) + .blockingSubscribe(action, consumer); + + assertTrue("" + errors, errors.isEmpty()); + + verify(action, never()).run(); + verify(consumer).accept(any(TestException.class)); + }); + } + + @Test + public void twoArgErrorAsync() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action action = mock(Action.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Completable.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(action, consumer); + + assertTrue("" + errors, errors.isEmpty()); + + verify(action, never()).run(); + verify(consumer).accept(any(TestException.class)); + }); + } + + @Test + public void twoArgErrorFails() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action action = mock(Action.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + doThrow(new TestException()).when(consumer).accept(any()); + + Completable.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(action, consumer); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(action, never()).run(); + verify(consumer).accept(any(TestException.class)); + }); + } + + @Test + public void twoArgInterrupted() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action onDispose = mock(Action.class); + + Action action = mock(Action.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Thread.currentThread().interrupt(); + + Completable.never() + .doOnDispose(onDispose) + .blockingSubscribe(action, consumer); + + assertTrue("" + errors, errors.isEmpty()); + + verify(onDispose).run(); + verify(action, never()).run(); + verify(consumer).accept(any(InterruptedException.class)); + }); + } + + @Test + public void observerComplete() { + TestObserver to = new TestObserver<>(); + + Completable.complete() + .blockingSubscribe(to); + + to.assertResult(); + } + + @Test + public void observerCompleteAsync() { + TestObserver to = new TestObserver<>(); + + Completable.complete() + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(to); + + to.assertResult(); + } + + @Test + public void observerError() { + TestObserver to = new TestObserver<>(); + + Completable.error(new TestException()) + .blockingSubscribe(to); + + to.assertFailure(TestException.class); + } + + @Test + public void observerErrorAsync() { + TestObserver to = new TestObserver<>(); + + Completable.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(to); + + to.assertFailure(TestException.class); + } + + @Test + public void observerDispose() throws Throwable { + Action onDispose = mock(Action.class); + + TestObserver to = new TestObserver<>(); + to.dispose(); + + Completable.never() + .doOnDispose(onDispose) + .blockingSubscribe(to); + + to.assertEmpty(); + + verify(onDispose).run(); + } + + @Test + public void ovserverInterrupted() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action onDispose = mock(Action.class); + + TestObserver to = new TestObserver<>(); + + Thread.currentThread().interrupt(); + + Completable.never() + .doOnDispose(onDispose) + .blockingSubscribe(to); + + assertTrue("" + errors, errors.isEmpty()); + + verify(onDispose).run(); + to.assertFailure(InterruptedException.class); + }); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeBlockingSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeBlockingSubscribeTest.java new file mode 100644 index 0000000000..647d385eef --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeBlockingSubscribeTest.java @@ -0,0 +1,502 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Maybe; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class MaybeBlockingSubscribeTest { + + @Test + public void noArgSuccess() { + Maybe.just(1) + .blockingSubscribe(); + } + + @Test + public void noArgSuccessAsync() { + Maybe.just(1) + .delay(100, TimeUnit.MILLISECONDS) + .blockingSubscribe(); + } + + @Test + public void noArgEmpty() { + Maybe.empty() + .blockingSubscribe(); + } + + @Test + public void noArgEmptyAsync() { + Maybe.empty() + .delay(100, TimeUnit.MILLISECONDS) + .blockingSubscribe(); + } + + @Test + public void noArgError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Maybe.error(new TestException()) + .blockingSubscribe(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void noArgErrorAsync() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Maybe.error(new TestException()) + .delay(100, TimeUnit.MILLISECONDS, Schedulers.computation()) + .blockingSubscribe(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void oneArgSuccess() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + + Maybe.just(1) + .blockingSubscribe(success); + + verify(success).accept(1); + } + + @Test + public void oneArgSuccessAsync() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + + Maybe.just(1) + .delay(50, TimeUnit.MILLISECONDS) + .blockingSubscribe(success); + + verify(success).accept(1); + } + + @Test + public void oneArgEmpty() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + + Maybe.empty() + .blockingSubscribe(success); + + verify(success, never()).accept(any()); + } + + @Test + public void oneArgEmptyAsync() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + + Maybe.empty() + .delay(50, TimeUnit.MILLISECONDS) + .blockingSubscribe(success); + + verify(success, never()).accept(any()); + } + + @Test + public void oneArgSuccessFails() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + doThrow(new TestException()).when(success).accept(any()); + + Maybe.just(1) + .blockingSubscribe(success); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success).accept(1); + }); + } + + @Test + public void oneArgError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + + Maybe.error(new TestException()) + .blockingSubscribe(success); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success, never()).accept(any()); + }); + } + + @Test + public void oneArgErrorAsync() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + + Maybe.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation()) + .blockingSubscribe(success); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success, never()).accept(any()); + }); + } + + @Test + public void twoArgSuccess() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Maybe.just(1) + .blockingSubscribe(success, consumer); + + verify(success).accept(1); + verify(consumer, never()).accept(any()); + } + + @Test + public void twoArgSuccessAsync() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Maybe.just(1) + .delay(50, TimeUnit.MILLISECONDS) + .blockingSubscribe(success, consumer); + + verify(success).accept(any()); + verify(consumer, never()).accept(any()); + } + + @Test + public void twoArgEmpty() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Maybe.empty() + .blockingSubscribe(success, consumer); + + verify(success, never()).accept(any()); + verify(consumer, never()).accept(any()); + } + + @Test + public void twoArgEmptyAsync() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Maybe.empty() + .delay(50, TimeUnit.MILLISECONDS) + .blockingSubscribe(success, consumer); + + verify(success, never()).accept(any()); + verify(consumer, never()).accept(any()); + } + + @Test + public void twoArgSuccessFails() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + doThrow(new TestException()).when(success).accept(any()); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Maybe.just(1) + .blockingSubscribe(success, consumer); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success).accept(any()); + verify(consumer, never()).accept(any()); + }); + } + + @Test + public void twoArgError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Maybe.error(new TestException()) + .blockingSubscribe(success, consumer); + + assertTrue("" + errors, errors.isEmpty()); + + verify(success, never()).accept(any()); + verify(consumer).accept(any(TestException.class)); + }); + } + + @Test + public void twoArgErrorAsync() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Maybe.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation()) + .blockingSubscribe(success, consumer); + + assertTrue("" + errors, errors.isEmpty()); + + verify(success, never()).accept(any()); + verify(consumer).accept(any(TestException.class)); + }); + } + + @Test + public void twoArgErrorFails() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + doThrow(new TestException()).when(consumer).accept(any()); + + Maybe.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation()) + .blockingSubscribe(success, consumer); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success, never()).accept(any()); + verify(consumer).accept(any(TestException.class)); + }); + } + + @Test + public void threeArgSuccess() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + Action action = mock(Action.class); + + Maybe.just(1) + .blockingSubscribe(success, consumer, action); + + verify(success).accept(any()); + verify(consumer, never()).accept(any(Throwable.class)); + verify(action, never()).run(); + } + + @Test + public void threeArgEmpty() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + Action action = mock(Action.class); + + Maybe.empty() + .blockingSubscribe(success, consumer, action); + + verify(success, never()).accept(any()); + verify(consumer, never()).accept(any(Throwable.class)); + verify(action).run(); + } + + @Test + public void threeArgError() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + Action action = mock(Action.class); + + Maybe.error(new TestException()) + .blockingSubscribe(success, consumer, action); + + verify(success, never()).accept(any()); + verify(consumer).accept(any(TestException.class)); + verify(action, never()).run(); + } + + @Test + public void threeArgEmptyFails() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Action action = mock(Action.class); + doThrow(new TestException()).when(action).run(); + + Maybe.empty() + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation()) + .blockingSubscribe(success, consumer, action); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success, never()).accept(any()); + verify(consumer, never()).accept(any()); + verify(action).run(); + }); + } + + @Test + public void threeArgInterrupted() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action onDispose = mock(Action.class); + + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + Action action = mock(Action.class); + + Thread.currentThread().interrupt(); + + Maybe.never() + .doOnDispose(onDispose) + .blockingSubscribe(success, consumer, action); + + assertTrue("" + errors, errors.isEmpty()); + + verify(onDispose).run(); + verify(success, never()).accept(any()); + verify(action, never()).run(); + verify(consumer).accept(any(InterruptedException.class)); + }); + } + + @Test + public void observerSuccess() { + TestObserver to = new TestObserver<>(); + + Maybe.just(1) + .blockingSubscribe(to); + + to.assertResult(1); + } + + @Test + public void observerSuccessAsync() { + TestObserver to = new TestObserver<>(); + + Maybe.just(1) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation()) + .blockingSubscribe(to); + + to.assertResult(1); + } + + @Test + public void observerEmpty() { + TestObserver to = new TestObserver<>(); + + Maybe.empty() + .blockingSubscribe(to); + + to.assertResult(); + } + + @Test + public void observerEmptyAsync() { + TestObserver to = new TestObserver<>(); + + Maybe.empty() + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation()) + .blockingSubscribe(to); + + to.assertResult(); + } + + @Test + public void observerError() { + TestObserver to = new TestObserver<>(); + + Maybe.error(new TestException()) + .blockingSubscribe(to); + + to.assertFailure(TestException.class); + } + + @Test + public void observerErrorAsync() { + TestObserver to = new TestObserver<>(); + + Maybe.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation()) + .blockingSubscribe(to); + + to.assertFailure(TestException.class); + } + + @Test + public void observerDispose() throws Throwable { + Action onDispose = mock(Action.class); + + TestObserver to = new TestObserver<>(); + to.dispose(); + + Maybe.never() + .doOnDispose(onDispose) + .blockingSubscribe(to); + + to.assertEmpty(); + + verify(onDispose).run(); + } + + @Test + public void ovserverInterrupted() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action onDispose = mock(Action.class); + + TestObserver to = new TestObserver<>(); + + Thread.currentThread().interrupt(); + + Maybe.never() + .doOnDispose(onDispose) + .blockingSubscribe(to); + + assertTrue("" + errors, errors.isEmpty()); + + verify(onDispose).run(); + to.assertFailure(InterruptedException.class); + }); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleBlockingSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleBlockingSubscribeTest.java new file mode 100644 index 0000000000..50eceede5c --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleBlockingSubscribeTest.java @@ -0,0 +1,343 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleBlockingSubscribeTest { + + @Test + public void noArgSuccess() { + Single.just(1) + .blockingSubscribe(); + } + + @Test + public void noArgSuccessAsync() { + Single.just(1) + .delay(100, TimeUnit.MILLISECONDS) + .blockingSubscribe(); + } + + @Test + public void noArgError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Single.error(new TestException()) + .blockingSubscribe(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void noArgErrorAsync() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Single.error(new TestException()) + .delay(100, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void oneArgSuccess() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + + Single.just(1) + .blockingSubscribe(success); + + verify(success).accept(1); + } + + @Test + public void oneArgSuccessAsync() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + + Single.just(1) + .delay(50, TimeUnit.MILLISECONDS) + .blockingSubscribe(success); + + verify(success).accept(1); + } + + @Test + public void oneArgSuccessFails() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + doThrow(new TestException()).when(success).accept(any()); + + Single.just(1) + .blockingSubscribe(success); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success).accept(1); + }); + } + + @Test + public void oneArgError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + + Single.error(new TestException()) + .blockingSubscribe(success); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success, never()).accept(any()); + }); + } + + @Test + public void oneArgErrorAsync() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + + Single.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(success); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success, never()).accept(any()); + }); + } + + @Test + public void twoArgSuccess() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Single.just(1) + .blockingSubscribe(success, consumer); + + verify(success).accept(1); + verify(consumer, never()).accept(any()); + } + + @Test + public void twoArgSuccessAsync() throws Throwable { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Single.just(1) + .delay(50, TimeUnit.MILLISECONDS) + .blockingSubscribe(success, consumer); + + verify(success).accept(any()); + verify(consumer, never()).accept(any()); + } + + @Test + public void twoArgSuccessFails() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + doThrow(new TestException()).when(success).accept(any()); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Single.just(1) + .blockingSubscribe(success, consumer); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success).accept(any()); + verify(consumer, never()).accept(any()); + }); + } + + @Test + public void twoArgError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Single.error(new TestException()) + .blockingSubscribe(success, consumer); + + assertTrue("" + errors, errors.isEmpty()); + + verify(success, never()).accept(any()); + verify(consumer).accept(any(TestException.class)); + }); + } + + @Test + public void twoArgErrorAsync() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Single.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(success, consumer); + + assertTrue("" + errors, errors.isEmpty()); + + verify(success, never()).accept(any()); + verify(consumer).accept(any(TestException.class)); + }); + } + + @Test + public void twoArgErrorFails() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + doThrow(new TestException()).when(consumer).accept(any()); + + Single.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(success, consumer); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + + verify(success, never()).accept(any()); + verify(consumer).accept(any(TestException.class)); + }); + } + + @Test + public void twoArgInterrupted() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action onDispose = mock(Action.class); + + @SuppressWarnings("unchecked") + Consumer success = mock(Consumer.class); + @SuppressWarnings("unchecked") + Consumer consumer = mock(Consumer.class); + + Thread.currentThread().interrupt(); + + Single.never() + .doOnDispose(onDispose) + .blockingSubscribe(success, consumer); + + assertTrue("" + errors, errors.isEmpty()); + + verify(onDispose).run(); + verify(success, never()).accept(any()); + verify(consumer).accept(any(InterruptedException.class)); + }); + } + + @Test + public void observerSuccess() { + TestObserver to = new TestObserver<>(); + + Single.just(1) + .blockingSubscribe(to); + + to.assertResult(1); + } + + @Test + public void observerSuccessAsync() { + TestObserver to = new TestObserver<>(); + + Single.just(1) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(to); + + to.assertResult(1); + } + + @Test + public void observerError() { + TestObserver to = new TestObserver<>(); + + Single.error(new TestException()) + .blockingSubscribe(to); + + to.assertFailure(TestException.class); + } + + @Test + public void observerErrorAsync() { + TestObserver to = new TestObserver<>(); + + Single.error(new TestException()) + .delay(50, TimeUnit.MILLISECONDS, Schedulers.computation(), true) + .blockingSubscribe(to); + + to.assertFailure(TestException.class); + } + + @Test + public void observerDispose() throws Throwable { + Action onDispose = mock(Action.class); + + TestObserver to = new TestObserver<>(); + to.dispose(); + + Single.never() + .doOnDispose(onDispose) + .blockingSubscribe(to); + + to.assertEmpty(); + + verify(onDispose).run(); + } + + @Test + public void ovserverInterrupted() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Action onDispose = mock(Action.class); + + TestObserver to = new TestObserver<>(); + + Thread.currentThread().interrupt(); + + Single.never() + .doOnDispose(onDispose) + .blockingSubscribe(to); + + assertTrue("" + errors, errors.isEmpty()); + + verify(onDispose).run(); + to.assertFailure(InterruptedException.class); + }); + } +} From 13473da61366945f49aed5a29729841836abf2ab Mon Sep 17 00:00:00 2001 From: David Karnok Date: Fri, 24 Jan 2020 17:36:18 +0100 Subject: [PATCH 10/37] 3.x: Fix many marbles in Maybe (#6866) --- .../java/io/reactivex/rxjava3/core/Maybe.java | 80 ++++++++++++------- 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 0d0d6f5473..375a439e65 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -562,6 +562,8 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends /** * Provides an API (via a cold {@code Maybe}) that bridges the reactive world with the callback-style world. *

+ * + *

* Example: *


      * Maybe.<Event>create(emitter -> {
@@ -615,6 +617,8 @@ public static  Maybe create(@NonNull MaybeOnSubscribe onSubscribe) {
     /**
      * Calls a {@link Supplier} for each individual {@link MaybeObserver} to return the actual {@link MaybeSource} source to
      * be subscribed to.
+     * 

+ * *

*
Scheduler:
*
{@code defer} does not operate by default on a particular {@link Scheduler}.
@@ -683,7 +687,7 @@ public static Maybe error(@NonNull Throwable throwable) { * Returns a {@code Maybe} that invokes a {@link MaybeObserver}'s {@link MaybeObserver#onError onError} method when the * {@code MaybeObserver} subscribes to it. *

- * + * *

*
Scheduler:
*
{@code error} does not operate by default on a particular {@link Scheduler}.
@@ -708,6 +712,8 @@ public static Maybe error(@NonNull Supplier supplier /** * Returns a {@code Maybe} instance that runs the given {@link Action} for each subscriber and * emits either its exception or simply completes. + *

+ * *

*
Scheduler:
*
{@code fromAction} does not operate by default on a particular {@link Scheduler}.
@@ -734,7 +740,8 @@ public static Maybe fromAction(@NonNull Action action) { /** * Wraps a {@link CompletableSource} into a {@code Maybe}. - * + *

+ * *

*
Scheduler:
*
{@code fromCompletable} does not operate by default on a particular {@link Scheduler}.
@@ -754,7 +761,8 @@ public static Maybe fromCompletable(@NonNull CompletableSource completabl /** * Wraps a {@link SingleSource} into a {@code Maybe}. - * + *

+ * *

*
Scheduler:
*
{@code fromSingle} does not operate by default on a particular {@link Scheduler}.
@@ -778,6 +786,8 @@ public static Maybe fromSingle(@NonNull SingleSource single) { * considering a {@code null} result from the {@code Callable} as indication for valueless completion * via {@code onComplete}. *

+ * + *

* This operator allows you to defer the execution of the given {@code Callable} until a {@code MaybeObserver} * subscribes to the returned {@code Maybe}. In other terms, this source operator evaluates the given * {@code Callable} "lazily". @@ -820,7 +830,7 @@ public static Maybe fromSingle(@NonNull SingleSource single) { /** * Converts a {@link Future} into a {@code Maybe}, treating a {@code null} result as an indication of emptiness. *

- * + * *

* The operator calls {@link Future#get()}, which is a blocking method, on the subscription thread. * It is recommended applying {@link #subscribeOn(Scheduler)} to move this blocking wait to a @@ -854,7 +864,7 @@ public static Maybe fromSingle(@NonNull SingleSource single) { /** * Converts a {@link Future} into a {@code Maybe}, with a timeout on the {@code Future}. *

- * + * *

* The operator calls {@link Future#get(long, TimeUnit)}, which is a blocking method, on the subscription thread. * It is recommended applying {@link #subscribeOn(Scheduler)} to move this blocking wait to a @@ -893,6 +903,8 @@ public static Maybe fromSingle(@NonNull SingleSource single) { /** * Returns a {@code Maybe} instance that runs the given {@link Runnable} for each subscriber and * emits either its exception or simply completes. + *

+ * *

*
Scheduler:
*
{@code fromRunnable} does not operate by default on a particular {@link Scheduler}.
@@ -989,6 +1001,8 @@ public static Maybe fromRunnable(@NonNull Runnable run) { /** * Merges an {@link Iterable} sequence of {@link MaybeSource} instances into a single {@link Flowable} sequence, * running all {@code MaybeSource}s at once. + *

+ * *

*
Backpressure:
*
The operator honors backpressure from downstream.
@@ -1025,6 +1039,8 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends MaybeSo /** * Merges a {@link Publisher} sequence of {@link MaybeSource} instances into a single {@link Flowable} sequence, * running all {@code MaybeSource}s at once. + *

+ * *

*
Backpressure:
*
The operator honors backpressure from downstream.
@@ -1061,6 +1077,8 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends MaybeS /** * Merges a {@link Publisher} sequence of {@link MaybeSource} instances into a single {@link Flowable} sequence, * running at most maxConcurrency {@code MaybeSource}s at once. + *

+ * *

*
Backpressure:
*
The operator honors backpressure from downstream.
@@ -1134,7 +1152,7 @@ public static Maybe merge(@NonNull MaybeSource - * + * *

* You can combine items emitted by multiple {@code MaybeSource}s so that they appear as a single {@code Flowable}, by * using the {@code merge} method. @@ -1183,7 +1201,7 @@ public static Flowable merge( /** * Flattens three {@link MaybeSource}s into a single {@link Flowable}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code MaybeSource}s so that they appear as a single {@code Flowable}, by using * the {@code merge} method. @@ -1236,7 +1254,7 @@ public static Flowable merge( /** * Flattens four {@link MaybeSource}s into a single {@link Flowable}, without any transformation. *

- * + * *

* You can combine items emitted by multiple {@code MaybeSource}s so that they appear as a single {@code Flowable}, by using * the {@code merge} method. @@ -1292,6 +1310,8 @@ public static Flowable merge( /** * Merges an array sequence of {@link MaybeSource} instances into a single {@link Flowable} sequence, * running all {@code MaybeSource}s at once. + *

+ * *

*
Backpressure:
*
The operator honors backpressure from downstream.
@@ -1340,12 +1360,12 @@ public static Flowable mergeArray(MaybeSource... sources) { * successfully emitted items from each of the source {@code MaybeSource}s without being interrupted by an error * notification from one of them. *

+ * + *

* This behaves like {@link #merge(Publisher)} except that if any of the merged {@code MaybeSource}s notify of an * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code MaybeSource}s have finished emitting items. *

- * - *

* Even if multiple merged {@code MaybeSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its subscribers once. *

@@ -1381,11 +1401,13 @@ public static Flowable mergeArrayDelayError(@NonNull MaybeSource + * + *

* This behaves like {@link #merge(Publisher)} except that if any of the merged {@code MaybeSource}s notify of an * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code MaybeSource}s have finished emitting items. *

- * + * *

* Even if multiple merged {@code MaybeSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its subscribers once. @@ -1417,12 +1439,12 @@ public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? exten * receive all successfully emitted items from all of the source {@code MaybeSource}s without being interrupted by * an error notification from one of them or even the main {@code Publisher}. *

+ * + *

* This behaves like {@link #merge(Publisher)} except that if any of the merged {@code MaybeSource}s notify of an * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code MaybeSource}s and the main {@code Publisher} have finished emitting items. *

- * - *

* Even if multiple merged {@code MaybeSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its subscribers once. *

@@ -1453,12 +1475,12 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte * receive all successfully emitted items from all of the source {@code MaybeSource}s without being interrupted by * an error notification from one of them or even the main {@code Publisher} as well as limiting the total number of active {@code MaybeSource}s. *

+ * + *

* This behaves like {@link #merge(Publisher, int)} except that if any of the merged {@code MaybeSource}s notify of an * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that * error notification until all of the merged {@code MaybeSource}s and the main {@code Publisher} have finished emitting items. *

- * - *

* Even if multiple merged {@code MaybeSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its subscribers once. *

@@ -1495,12 +1517,12 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte * successfully emitted items from each of the source {@code MaybeSource}s without being interrupted by an error * notification from one of them. *

+ * + *

* This behaves like {@link #merge(MaybeSource, MaybeSource)} except that if any of the merged {@code MaybeSource}s * notify of an error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from * propagating that error notification until all of the merged {@code MaybeSource}s have finished emitting items. *

- * - *

* Even if both merged {@code MaybeSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its subscribers once. *

@@ -1534,13 +1556,13 @@ public static Flowable mergeDelayError(@NonNull MaybeSource * successfully emitted items from all of the source {@code MaybeSource}s without being interrupted by an error * notification from one of them. *

+ * + *

* This behaves like {@link #merge(MaybeSource, MaybeSource, MaybeSource)} except that if any of the merged * {@code MaybeSource}s notify of an error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain * from propagating that error notification until all of the merged {@code MaybeSource}s have finished emitting * items. *

- * - *

* Even if multiple merged {@code MaybeSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its subscribers once. *

@@ -1578,13 +1600,13 @@ public static Flowable mergeDelayError(@NonNull MaybeSource * successfully emitted items from all of the source {@code MaybeSource}s without being interrupted by an error * notification from one of them. *

+ * + *

* This behaves like {@link #merge(MaybeSource, MaybeSource, MaybeSource, MaybeSource)} except that if any of * the merged {@code MaybeSource}s notify of an error via {@link Subscriber#onError onError}, {@code mergeDelayError} * will refrain from propagating that error notification until all of the merged {@code MaybeSource}s have finished * emitting items. *

- * - *

* Even if multiple merged {@code MaybeSource}s send {@code onError} notifications, {@code mergeDelayError} will only * invoke the {@code onError} method of its subscribers once. *

@@ -1649,7 +1671,7 @@ public static Maybe never() { * Returns a {@link Single} that emits a {@link Boolean} value that indicates whether two {@link MaybeSource} sequences are the * same by comparing the items emitted by each {@code MaybeSource} pairwise. *

- * + * *

*
Scheduler:
*
{@code sequenceEqual} does not operate by default on a particular {@link Scheduler}.
@@ -1677,7 +1699,7 @@ public static Single sequenceEqual(@NonNull MaybeSource - * + * *
*
Scheduler:
*
{@code sequenceEqual} does not operate by default on a particular {@link Scheduler}.
@@ -1709,7 +1731,7 @@ public static Single sequenceEqual(@NonNull MaybeSource - * + * *
*
Scheduler:
*
{@code timer} operates by default on the {@code computation} {@link Scheduler}.
@@ -1733,7 +1755,7 @@ public static Maybe timer(long delay, @NonNull TimeUnit unit) { /** * Returns a {@code Maybe} that emits {@code 0L} after a specified delay on a specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -1762,6 +1784,8 @@ public static Maybe timer(long delay, @NonNull TimeUnit unit, @NonNull Sch /** * Advanced use only: creates a {@code Maybe} instance without * any safeguards by using a callback that is called with a {@link MaybeObserver}. + *

+ * *

*
Scheduler:
*
{@code unsafeCreate} does not operate by default on a particular {@link Scheduler}.
@@ -1787,7 +1811,7 @@ public static Maybe unsafeCreate(@NonNull MaybeSource onSubscribe) { * Constructs a {@code Maybe} that creates a dependent resource object which is disposed of when the * generated {@link MaybeSource} terminates or the downstream calls dispose(). *

- * + * *

*
Scheduler:
*
{@code using} does not operate by default on a particular {@link Scheduler}.
@@ -1818,7 +1842,7 @@ public static Maybe using(@NonNull Supplier resourceSuppl * Constructs a {@code Maybe} that creates a dependent resource object which is disposed first ({code eager == true}) * when the generated {@link MaybeSource} terminates or the downstream disposes; or after ({code eager == false}). *

- * + * *

* Eager disposal is particularly appropriate for a synchronous {@code Maybe} that reuses resources. {@code disposeAction} will * only be called once per subscription. @@ -1859,6 +1883,8 @@ public static Maybe using(@NonNull Supplier resourceSuppl /** * Wraps a {@link MaybeSource} instance into a new {@code Maybe} instance if not already a {@code Maybe} * instance. + *

+ * *

*
Scheduler:
*
{@code wrap} does not operate by default on a particular {@link Scheduler}.
From ad1840b1b591206e5eeb10c07b1b126fbbac3560 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Fri, 24 Jan 2020 22:44:22 +0100 Subject: [PATCH 11/37] 3.x: Add onErrorComplete to Flowable, Observable and Single (#6867) * 3.x: Add onErrorComplete to F/O/S * Add version tags. --- .../io/reactivex/rxjava3/core/Flowable.java | 54 ++++++- .../java/io/reactivex/rxjava3/core/Maybe.java | 4 + .../io/reactivex/rxjava3/core/Observable.java | 43 ++++++ .../io/reactivex/rxjava3/core/Single.java | 43 ++++++ .../flowable/FlowableOnErrorComplete.java | 107 +++++++++++++ .../operators/maybe/MaybeOnErrorComplete.java | 7 +- .../observable/ObservableOnErrorComplete.java | 106 +++++++++++++ .../single/SingleOnErrorComplete.java | 43 ++++++ .../flowable/FlowableOnErrorCompleteTest.java | 143 ++++++++++++++++++ .../ObservableOnErrorCompleteTest.java | 134 ++++++++++++++++ .../single/SingleOnErrorCompleteTest.java | 113 ++++++++++++++ 11 files changed, 793 insertions(+), 4 deletions(-) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorComplete.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorComplete.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorComplete.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorCompleteTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorCompleteTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorCompleteTest.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Flowable.java b/src/main/java/io/reactivex/rxjava3/core/Flowable.java index 0106f42ce9..a627eb3474 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Flowable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Flowable.java @@ -19,6 +19,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; +import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.flowables.*; @@ -28,7 +29,7 @@ import io.reactivex.rxjava3.internal.jdk8.*; import io.reactivex.rxjava3.internal.operators.flowable.*; import io.reactivex.rxjava3.internal.operators.mixed.*; -import io.reactivex.rxjava3.internal.operators.observable.ObservableFromPublisher; +import io.reactivex.rxjava3.internal.operators.observable.*; import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.internal.subscribers.*; import io.reactivex.rxjava3.internal.util.*; @@ -12308,6 +12309,57 @@ public final Flowable onBackpressureLatest() { return RxJavaPlugins.onAssembly(new FlowableOnBackpressureLatest<>(this)); } + /** + * Returns a {@code Flowable} instance that if the current {@code Flowable} emits an error, it will emit an {@code onComplete} + * and swallow the throwable. + *

+ * + *

+ *
Backpressure:
+ *
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure + * behavior.
+ *
Scheduler:
+ *
{@code onErrorComplete} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @return the new {@code Flowable} instance + * @since 3.0.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.PASS_THROUGH) + @NonNull + public final Flowable onErrorComplete() { + return onErrorComplete(Functions.alwaysTrue()); + } + + /** + * Returns a {@code Flowable} instance that if the current {@code Flowable} emits an error and the predicate returns + * {@code true}, it will emit an {@code onComplete} and swallow the throwable. + *

+ * + *

+ *
Backpressure:
+ *
The operator doesn't interfere with backpressure which is determined by the current {@code Flowable}'s backpressure + * behavior.
+ *
Scheduler:
+ *
{@code onErrorComplete} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param predicate the predicate to call when an {@link Throwable} is emitted which should return {@code true} + * if the {@code Throwable} should be swallowed and replaced with an {@code onComplete}. + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code predicate} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @BackpressureSupport(BackpressureKind.PASS_THROUGH) + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Flowable onErrorComplete(@NonNull Predicate predicate) { + Objects.requireNonNull(predicate, "predicate is null"); + + return RxJavaPlugins.onAssembly(new FlowableOnErrorComplete<>(this, predicate)); + } + /** * Resumes the flow with a {@link Publisher} returned for the failure {@link Throwable} of the current {@code Flowable} by a * function instead of signaling the error via {@code onError}. diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 375a439e65..1d385ce148 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -4042,6 +4042,8 @@ public final Single toSingle() { /** * Returns a {@code Maybe} instance that if this {@code Maybe} emits an error, it will emit an {@code onComplete} * and swallow the throwable. + *

+ * *

*
Scheduler:
*
{@code onErrorComplete} does not operate by default on a particular {@link Scheduler}.
@@ -4058,6 +4060,8 @@ public final Maybe onErrorComplete() { /** * Returns a {@code Maybe} instance that if this {@code Maybe} emits an error and the predicate returns * {@code true}, it will emit an {@code onComplete} and swallow the throwable. + *

+ * *

*
Scheduler:
*
{@code onErrorComplete} does not operate by default on a particular {@link Scheduler}.
diff --git a/src/main/java/io/reactivex/rxjava3/core/Observable.java b/src/main/java/io/reactivex/rxjava3/core/Observable.java index 57456a9545..f599ce0eeb 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Observable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Observable.java @@ -10346,6 +10346,49 @@ public final Observable ofType(@NonNull Class clazz) { return filter(Functions.isInstanceOf(clazz)).cast(clazz); } + /** + * Returns an {@code Observable} instance that if the current {@code Observable} emits an error, it will emit an {@code onComplete} + * and swallow the throwable. + *

+ * + *

+ *
Scheduler:
+ *
{@code onErrorComplete} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @return the new {@code Observable} instance + * @since 3.0.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Observable onErrorComplete() { + return onErrorComplete(Functions.alwaysTrue()); + } + + /** + * Returns an {@code Observable} instance that if the current {@code Observable} emits an error and the predicate returns + * {@code true}, it will emit an {@code onComplete} and swallow the throwable. + *

+ * + *

+ *
Scheduler:
+ *
{@code onErrorComplete} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param predicate the predicate to call when an {@link Throwable} is emitted which should return {@code true} + * if the {@code Throwable} should be swallowed and replaced with an {@code onComplete}. + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code predicate} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Observable onErrorComplete(@NonNull Predicate predicate) { + Objects.requireNonNull(predicate, "predicate is null"); + + return RxJavaPlugins.onAssembly(new ObservableOnErrorComplete<>(this, predicate)); + } + /** * Resumes the flow with an {@link ObservableSource} returned for the failure {@link Throwable} of the current {@code Observable} by a * function instead of signaling the error via {@code onError}. diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 216d3deb87..f6e41cee5c 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -3439,6 +3439,49 @@ public final Single onErrorResumeWith(@NonNull SingleSource fall return onErrorResumeNext(Functions.justFunction(fallback)); } + /** + * Returns a {@link Maybe} instance that if the current {@code Single} emits an error, it will emit an {@code onComplete} + * and swallow the throwable. + *

+ * + *

+ *
Scheduler:
+ *
{@code onErrorComplete} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @return the new {@code Maybe} instance + * @since 3.0.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Maybe onErrorComplete() { + return onErrorComplete(Functions.alwaysTrue()); + } + + /** + * Returns a {@link Maybe} instance that if this {@code Single} emits an error and the predicate returns + * {@code true}, it will emit an {@code onComplete} and swallow the throwable. + *

+ * + *

+ *
Scheduler:
+ *
{@code onErrorComplete} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param predicate the predicate to call when an {@link Throwable} is emitted which should return {@code true} + * if the {@code Throwable} should be swallowed and replaced with an {@code onComplete}. + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code predicate} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Maybe onErrorComplete(@NonNull Predicate predicate) { + Objects.requireNonNull(predicate, "predicate is null"); + + return RxJavaPlugins.onAssembly(new SingleOnErrorComplete<>(this, predicate)); + } + /** * Resumes the flow with a {@link SingleSource} returned for the failure {@link Throwable} of the current {@code Single} by a * function instead of signaling the error via {@code onError}. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorComplete.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorComplete.java new file mode 100644 index 0000000000..c477917f35 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorComplete.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import org.reactivestreams.*; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.Predicate; +import io.reactivex.rxjava3.internal.subscriptions.SubscriptionHelper; + +/** + * Emits an onComplete if the source emits an onError and the predicate returns true for + * that Throwable. + * + * @param the value type + * @since 3.0.0 + */ +public final class FlowableOnErrorComplete extends AbstractFlowableWithUpstream { + + final Predicate predicate; + + public FlowableOnErrorComplete(Flowable source, + Predicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + protected void subscribeActual(Subscriber observer) { + source.subscribe(new OnErrorCompleteSubscriber<>(observer, predicate)); + } + + public static final class OnErrorCompleteSubscriber + implements FlowableSubscriber, Subscription { + + final Subscriber downstream; + + final Predicate predicate; + + Subscription upstream; + + public OnErrorCompleteSubscriber(Subscriber actual, Predicate predicate) { + this.downstream = actual; + this.predicate = predicate; + } + + @Override + public void onSubscribe(Subscription s) { + if (SubscriptionHelper.validate(this.upstream, s)) { + this.upstream = s; + + downstream.onSubscribe(this); + } + } + + @Override + public void onNext(T value) { + downstream.onNext(value); + } + + @Override + public void onError(Throwable e) { + boolean b; + + try { + b = predicate.test(e); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + downstream.onError(new CompositeException(e, ex)); + return; + } + + if (b) { + downstream.onComplete(); + } else { + downstream.onError(e); + } + } + + @Override + public void onComplete() { + downstream.onComplete(); + } + + @Override + public void cancel() { + upstream.cancel(); + } + + @Override + public void request(long n) { + upstream.request(n); + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorComplete.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorComplete.java index 8792a93cc5..277e207eaf 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorComplete.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorComplete.java @@ -37,10 +37,11 @@ public MaybeOnErrorComplete(MaybeSource source, @Override protected void subscribeActual(MaybeObserver observer) { - source.subscribe(new OnErrorCompleteMaybeObserver<>(observer, predicate)); + source.subscribe(new OnErrorCompleteMultiObserver<>(observer, predicate)); } - static final class OnErrorCompleteMaybeObserver implements MaybeObserver, Disposable { + public static final class OnErrorCompleteMultiObserver + implements MaybeObserver, SingleObserver, Disposable { final MaybeObserver downstream; @@ -48,7 +49,7 @@ static final class OnErrorCompleteMaybeObserver implements MaybeObserver, Disposable upstream; - OnErrorCompleteMaybeObserver(MaybeObserver actual, Predicate predicate) { + public OnErrorCompleteMultiObserver(MaybeObserver actual, Predicate predicate) { this.downstream = actual; this.predicate = predicate; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorComplete.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorComplete.java new file mode 100644 index 0000000000..6854a5ce6d --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorComplete.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.Predicate; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; + +/** + * Emits an onComplete if the source emits an onError and the predicate returns true for + * that Throwable. + * + * @param the value type + * @since 3.0.0 + */ +public final class ObservableOnErrorComplete extends AbstractObservableWithUpstream { + + final Predicate predicate; + + public ObservableOnErrorComplete(ObservableSource source, + Predicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + protected void subscribeActual(Observer observer) { + source.subscribe(new OnErrorCompleteObserver<>(observer, predicate)); + } + + public static final class OnErrorCompleteObserver + implements Observer, Disposable { + + final Observer downstream; + + final Predicate predicate; + + Disposable upstream; + + public OnErrorCompleteObserver(Observer actual, Predicate predicate) { + this.downstream = actual; + this.predicate = predicate; + } + + @Override + public void onSubscribe(Disposable d) { + if (DisposableHelper.validate(this.upstream, d)) { + this.upstream = d; + + downstream.onSubscribe(this); + } + } + + @Override + public void onNext(T value) { + downstream.onNext(value); + } + + @Override + public void onError(Throwable e) { + boolean b; + + try { + b = predicate.test(e); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + downstream.onError(new CompositeException(e, ex)); + return; + } + + if (b) { + downstream.onComplete(); + } else { + downstream.onError(e); + } + } + + @Override + public void onComplete() { + downstream.onComplete(); + } + + @Override + public void dispose() { + upstream.dispose(); + } + + @Override + public boolean isDisposed() { + return upstream.isDisposed(); + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorComplete.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorComplete.java new file mode 100644 index 0000000000..7be9bd817c --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorComplete.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.functions.Predicate; +import io.reactivex.rxjava3.internal.operators.maybe.MaybeOnErrorComplete; + +/** + * Emits an onComplete if the source emits an onError and the predicate returns true for + * that Throwable. + * + * @param the value type + * @since 3.0.0 + */ +public final class SingleOnErrorComplete extends Maybe { + + final Single source; + + final Predicate predicate; + + public SingleOnErrorComplete(Single source, + Predicate predicate) { + this.source = source; + this.predicate = predicate; + } + + @Override + protected void subscribeActual(MaybeObserver observer) { + source.subscribe(new MaybeOnErrorComplete.OnErrorCompleteMultiObserver(observer, predicate)); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorCompleteTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorCompleteTest.java new file mode 100644 index 0000000000..c1c89cbe27 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnErrorCompleteTest.java @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import static org.junit.Assert.*; + +import java.io.IOException; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.subscribers.TestSubscriber; +import io.reactivex.rxjava3.testsupport.*; + +public class FlowableOnErrorCompleteTest { + + @Test + public void normal() { + Flowable.range(1, 10) + .onErrorComplete() + .test() + .assertResult(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void normalBackpressured() { + Flowable.range(1, 10) + .onErrorComplete() + .test(0) + .assertEmpty() + .requestMore(3) + .assertValuesOnly(1, 2, 3) + .requestMore(3) + .assertValuesOnly(1, 2, 3, 4, 5, 6) + .requestMore(4) + .assertResult(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void empty() { + Flowable.empty() + .onErrorComplete() + .test() + .assertResult(); + } + + @Test + public void error() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Flowable.error(new TestException()) + .onErrorComplete() + .test() + .assertResult(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void errorMatches() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Flowable.error(new TestException()) + .onErrorComplete(error -> error instanceof TestException) + .test() + .assertResult(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void errorNotMatches() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Flowable.error(new IOException()) + .onErrorComplete(error -> error instanceof TestException) + .test() + .assertFailure(IOException.class); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void errorPredicateCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestSubscriberEx ts = Flowable.error(new IOException()) + .onErrorComplete(error -> { throw new TestException(); }) + .subscribeWith(new TestSubscriberEx<>()) + .assertFailure(CompositeException.class); + + TestHelper.assertError(ts, 0, IOException.class); + TestHelper.assertError(ts, 1, TestException.class); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void itemsThenError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Flowable.range(1, 5) + .map(v -> 4 / (3 - v)) + .onErrorComplete() + .test() + .assertResult(2, 4); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void cancel() { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = pp + .onErrorComplete() + .test(); + + assertTrue("No subscribers?!", pp.hasSubscribers()); + + ts.cancel(); + + assertFalse("Still subscribers?!", pp.hasSubscribers()); + } + + @Test + public void onSubscribe() { + TestHelper.checkDoubleOnSubscribeFlowable(f -> f.onErrorComplete()); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorCompleteTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorCompleteTest.java new file mode 100644 index 0000000000..4c37745834 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableOnErrorCompleteTest.java @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import static org.junit.Assert.*; + +import java.io.IOException; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.testsupport.*; + +public class ObservableOnErrorCompleteTest { + + @Test + public void normal() { + Observable.range(1, 10) + .onErrorComplete() + .test() + .assertResult(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void empty() { + Observable.empty() + .onErrorComplete() + .test() + .assertResult(); + } + + @Test + public void error() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Observable.error(new TestException()) + .onErrorComplete() + .test() + .assertResult(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void errorMatches() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Observable.error(new TestException()) + .onErrorComplete(error -> error instanceof TestException) + .test() + .assertResult(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void errorNotMatches() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Observable.error(new IOException()) + .onErrorComplete(error -> error instanceof TestException) + .test() + .assertFailure(IOException.class); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void errorPredicateCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestObserverEx to = Observable.error(new IOException()) + .onErrorComplete(error -> { throw new TestException(); }) + .subscribeWith(new TestObserverEx<>()) + .assertFailure(CompositeException.class); + + TestHelper.assertError(to, 0, IOException.class); + TestHelper.assertError(to, 1, TestException.class); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void itemsThenError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Observable.range(1, 5) + .map(v -> 4 / (3 - v)) + .onErrorComplete() + .test() + .assertResult(2, 4); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void dispose() { + PublishSubject ps = PublishSubject.create(); + + TestObserver to = ps + .onErrorComplete() + .test(); + + assertTrue("No subscribers?!", ps.hasObservers()); + + to.dispose(); + + assertFalse("Still subscribers?!", ps.hasObservers()); + } + + @Test + public void onSubscribe() { + TestHelper.checkDoubleOnSubscribeObservable(f -> f.onErrorComplete()); + } + + @Test + public void isDisposed() { + TestHelper.checkDisposed(PublishSubject.create().onErrorComplete()); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorCompleteTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorCompleteTest.java new file mode 100644 index 0000000000..189759d6c6 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOnErrorCompleteTest.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import static org.junit.Assert.*; + +import java.io.IOException; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.subjects.*; +import io.reactivex.rxjava3.testsupport.*; + +public class SingleOnErrorCompleteTest { + + @Test + public void normal() { + Single.just(1) + .onErrorComplete() + .test() + .assertResult(1); + } + + @Test + public void error() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Single.error(new TestException()) + .onErrorComplete() + .test() + .assertResult(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void errorMatches() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Single.error(new TestException()) + .onErrorComplete(error -> error instanceof TestException) + .test() + .assertResult(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void errorNotMatches() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Single.error(new IOException()) + .onErrorComplete(error -> error instanceof TestException) + .test() + .assertFailure(IOException.class); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void errorPredicateCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + TestObserverEx to = Single.error(new IOException()) + .onErrorComplete(error -> { throw new TestException(); }) + .subscribeWith(new TestObserverEx<>()) + .assertFailure(CompositeException.class); + + TestHelper.assertError(to, 0, IOException.class); + TestHelper.assertError(to, 1, TestException.class); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void dispose() { + SingleSubject ss = SingleSubject.create(); + + TestObserver to = ss + .onErrorComplete() + .test(); + + assertTrue("No subscribers?!", ss.hasObservers()); + + to.dispose(); + + assertFalse("Still subscribers?!", ss.hasObservers()); + } + + @Test + public void onSubscribe() { + TestHelper.checkDoubleOnSubscribeSingleToMaybe(f -> f.onErrorComplete()); + } + + @Test + public void isDisposed() { + TestHelper.checkDisposed(SingleSubject.create().onErrorComplete()); + } +} From b157b8684d812fa58e14250f1570925539df096c Mon Sep 17 00:00:00 2001 From: David Karnok Date: Sat, 25 Jan 2020 00:06:05 +0100 Subject: [PATCH 12/37] 3.x: Add Completable.onErrorResumeWith (#6868) --- .../reactivex/rxjava3/core/Completable.java | 27 +++++++++++++++++ .../java/io/reactivex/rxjava3/core/Maybe.java | 4 +-- .../CompletableResumeNextTest.java | 29 +++++++++++++++++-- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 0913ac398d..4a5bd55c39 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -2086,6 +2086,33 @@ public final Completable onErrorResumeNext(@NonNull Function + * + *

+ * You can use this to prevent errors from propagating or to supply fallback data should errors be + * encountered. + *

+ *
Scheduler:
+ *
{@code onErrorResumeWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param fallback + * the next {@code CompletableSource} that will take over if the current {@code Completable} encounters + * an error + * @return the new {@code Completable} instance + * @throws NullPointerException if {@code fallback} is {@code null} + * @see ReactiveX operators documentation: Catch + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Completable onErrorResumeWith(@NonNull CompletableSource fallback) { + Objects.requireNonNull(fallback, "fallback is null"); + return onErrorResumeNext(Functions.justFunction(fallback)); + } /** * Nulls out references to the upstream producer and downstream {@link CompletableObserver} if diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 1d385ce148..7bdfe05ee5 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -4084,7 +4084,7 @@ public final Maybe onErrorComplete(@NonNull Predicate pred * Resumes the flow with the given {@link MaybeSource} when the current {@code Maybe} fails instead of * signaling the error via {@code onError}. *

- * + * *

* You can use this to prevent errors from propagating or to supply fallback data should errors be * encountered. @@ -4112,7 +4112,7 @@ public final Maybe onErrorResumeWith(@NonNull MaybeSource fallba * Resumes the flow with a {@link MaybeSource} returned for the failure {@link Throwable} of the current {@code Maybe} by a * function instead of signaling the error via {@code onError}. *

- * + * *

* You can use this to prevent errors from propagating or to supply fallback data should errors be * encountered. diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNextTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNextTest.java index 5670264378..fb5390cdcc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNextTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableResumeNextTest.java @@ -13,18 +13,19 @@ package io.reactivex.rxjava3.internal.operators.completable; +import static org.mockito.Mockito.*; import org.junit.Test; import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.exceptions.TestException; -import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.internal.functions.Functions; import io.reactivex.rxjava3.testsupport.TestHelper; public class CompletableResumeNextTest extends RxJavaTest { @Test - public void resumeWithError() { + public void resumeNextError() { Completable.error(new TestException()) .onErrorResumeNext(Functions.justFunction(Completable.error(new TestException("second")))) .to(TestHelper.testConsumer()) @@ -58,4 +59,28 @@ public void disposed() { .onErrorResumeNext(Functions.justFunction(Completable.never())) ); } + + @Test + public void resumeWithNoError() throws Throwable { + Action action = mock(Action.class); + + Completable.complete() + .onErrorResumeWith(Completable.fromAction(action)) + .test() + .assertResult(); + + verify(action, never()).run(); + } + + @Test + public void resumeWithError() throws Throwable { + Action action = mock(Action.class); + + Completable.error(new TestException()) + .onErrorResumeWith(Completable.fromAction(action)) + .test() + .assertResult(); + + verify(action).run(); + } } From 320a675ec124cde872124d3bafd685e6a8998d0a Mon Sep 17 00:00:00 2001 From: akarnokd Date: Sat, 25 Jan 2020 00:08:49 +0100 Subject: [PATCH 13/37] Update Operator-Matrix generator and output --- docs/Operator-Matrix.md | 535 ++++++++++-------- .../reactivex/rxjava3/core/Completable.java | 1 + .../util/OperatorMatrixGenerator.java | 30 +- 3 files changed, 333 insertions(+), 233 deletions(-) diff --git a/docs/Operator-Matrix.md b/docs/Operator-Matrix.md index 3c3ef2c765..1259584fea 100644 --- a/docs/Operator-Matrix.md +++ b/docs/Operator-Matrix.md @@ -17,7 +17,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `blockingNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| `blockingSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| `blockingStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([6](#notes-6))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([7](#notes-7))| -`blockingSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`blockingSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `buffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([9](#notes-9))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([10](#notes-10))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([11](#notes-11))| `cache`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `cacheWithInitialCapacity`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([12](#notes-12))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([12](#notes-12))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([12](#notes-12))| @@ -32,211 +32,211 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `compose`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `concat`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `concatArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`concatArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`concatArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| `concatArrayEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([24](#notes-24))| -`concatArrayEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([25](#notes-25))| -`concatDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`concatArrayEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([25](#notes-25))| +`concatDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| `concatEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([26](#notes-26))| -`concatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`concatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`concatMapEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`concatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `concatWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `contains`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`count`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))| +`count`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))| `create`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`debounce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`defaultIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))| +`debounce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`defaultIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| `defer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `delay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `delaySubscription`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`dematerialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`distinct`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`distinctUntilChanged`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`doAfterNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`doAfterSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`dematerialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`distinct`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`distinctUntilChanged`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`doAfterNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`doAfterSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `doAfterTerminate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `doFinally`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnCancel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| -`doOnComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnDispose`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`doOnCancel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))| +`doOnComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnDispose`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `doOnError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnEvent`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnLifecycle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`doOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`doOnRequest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))| +`doOnEvent`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnLifecycle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`doOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`doOnRequest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| `doOnSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`doOnSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `doOnTerminate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`elementAt`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`elementAtOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`empty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))| +`elementAt`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`elementAtOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`empty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))| `error`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`filter`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`first`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))| -`firstElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`firstOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))| -`firstOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| -`firstStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))| +`filter`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`first`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| +`firstElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`firstOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))| +`firstOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))| +`firstStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| `flatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `flatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapPublisher`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapSingleElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenStreamAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenStreamAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`forEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| -`forEachWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| -`fromAction`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| +`flatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapPublisher`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapSingleElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenStreamAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenStreamAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`forEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))| +`forEachWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))| +`fromAction`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| `fromCallable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromCompletable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))| +`fromCompletable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))| `fromCompletionStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `fromFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| -`fromMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| -`fromPublisher`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromRunnable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| +`fromIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| +`fromMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| +`fromPublisher`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromRunnable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| `fromSupplier`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`generate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))| -`groupBy`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| -`groupJoin`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))| +`generate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| +`groupBy`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([76](#notes-76))| +`groupJoin`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([77](#notes-77))| `hide`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`ignoreElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`ignoreElements`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`interval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))| -`intervalRange`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))| -`isEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`join`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([76](#notes-76))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([76](#notes-76))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))| -`just`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`last`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))| -`lastElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`lastOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))| -`lastOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| -`lastStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))| +`ignoreElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`ignoreElements`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`interval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))| +`intervalRange`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))| +`isEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`join`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([77](#notes-77))| +`just`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`last`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| +`lastElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`lastOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))| +`lastOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))| +`lastStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| `lift`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `map`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `mapOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `materialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `merge`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`mergeArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`mergeArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`mergeArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`mergeArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `mergeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `mergeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `never`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `observeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`ofType`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([77](#notes-77))| -`onBackpressureBuffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))| -`onBackpressureDrop`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))| -`onBackpressureLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))| -`onErrorComplete`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`ofType`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))| +`onBackpressureBuffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| +`onBackpressureDrop`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| +`onBackpressureLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| +`onErrorComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `onErrorResumeNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`onErrorResumeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`onErrorReturn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`onErrorReturnItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`onErrorResumeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`onErrorReturn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`onErrorReturnItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| `onTerminateDetach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`parallel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))| -`publish`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))| -`range`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| -`rangeLong`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))| -`rebatchRequests`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))| -`reduce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))| -`reduceWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))| +`parallel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))| +`publish`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| +`range`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| +`rangeLong`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| +`rebatchRequests`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| +`reduce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| +`reduceWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| `repeat`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `repeatUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `repeatWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`replay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))| +`replay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| `retry`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`retryUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`retryUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| `retryWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`safeSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`scan`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))| -`scanWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))| -`sequenceEqual`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`serialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))| -`share`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))| -`single`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))| -`singleElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`singleOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))| -`singleOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| -`singleStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))| -`skip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| -`skipLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| -`skipUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| -`skipWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`sorted`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))| -`startWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`startWithArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))| -`startWithItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| -`startWithIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))| +`safeSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`scan`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| +`scanWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| +`sequenceEqual`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`serialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))| +`share`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| +`single`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| +`singleElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`singleOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))| +`singleOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))| +`singleStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| +`skip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| +`skipLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| +`skipUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))| +`skipWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`sorted`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))| +`startWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`startWithArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))| +`startWithItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))| +`startWithIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))| `subscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `subscribeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `subscribeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`switchIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))| -`switchMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`switchOnNextDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| -`take`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| -`takeLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| +`switchIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))| +`switchMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`switchOnNextDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`take`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| +`takeLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| `takeUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`takeWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`takeWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| `test`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`throttleFirst`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`throttleLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`throttleLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`throttleWithTimeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| -`timeInterval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`throttleFirst`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`throttleLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`throttleLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`throttleWithTimeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`timeInterval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| `timeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `timer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))| +`timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `to`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toCompletionStage`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)| +`toCompletionStage`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| `toList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| `toMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| -`toMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toMultimap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| -`toObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toSingleDefault`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([101](#notes-101))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([101](#notes-101))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toSingleDefault`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([103](#notes-103))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toSortedList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| `unsafeCreate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `unsubscribeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `using`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`window`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([101](#notes-101))| +`window`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([104](#notes-104))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([105](#notes-105))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([106](#notes-106))| `withLatestFrom`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([16](#notes-16))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([16](#notes-16))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([17](#notes-17))| -`wrap`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([103](#notes-103))| -`zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([104](#notes-104))| -`zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([105](#notes-105))| +`wrap`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([107](#notes-107))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([108](#notes-108))| +`zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([109](#notes-109))| +`zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([110](#notes-110))| #### Notes 1 Use [`contains()`](#contains).
@@ -266,81 +266,154 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat 25 No items to keep ordered. Use [`mergeArrayDelayError()`](#mergeArrayDelayError).
26 No items to keep ordered. Use [`merge()`](#merge).
27 Always empty thus no items to map.
-28 At most one item. Use [`flattenAsFlowable`](#flattenAsFlowable) or [`flattenAsObservable`](#flattenAsObservable).
-29 At most one item. Use [`flattenStreamAsFlowable`](#flattenStreamAsFlowable) or [`flattenStreamAsObservable`](#flattenStreamAsObservable).
-30 Never empty thus always 1.
-31 Always empty thus always 0.
-32 At most one item signaled so no subsequent items to work with.
-33 Always empty thus no items to work with.
-34 Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.
-35 At most one item, always distinct.
-36 Different terminology. Use [`doAfterSuccess()`](#doAfterSuccess).
-37 Different terminology. Use [`doAfterNext()`](#doAfterNext).
-38 Different terminology. Use [`doOnDispose()`](#doOnDispose).
-39 Always succeeds or fails, there is no `onComplete` signal.
-40 Different terminology. Use [`doOnCancel()`](#doOnCancel).
-41 At most one item. Use [`doOnEvent()`](#doOnEvent).
-42 Use [`doOnEach()`](#doOnEach).
-43 Different terminology. Use [`doOnSuccess()`](#doOnSuccess).
-44 Backpressure related and not supported outside `Flowable`.
-45 Different terminology. Use [`doOnNext()`](#doOnNext).
-46 At most one item with index 0. Use [`defaultIfEmpty`](#defaultIfEmpty).
-47 Always one item with index 0.
-48 At most one item with index 0. Use [`toSingle`](#toSingle).
-49 Use [`complete()`](#complete).
-50 At most one item. Use [`defaultIfEmpty`](#defaultIfEmpty).
-51 Always one item.
-52 At most one item, would be no-op.
-53 Always one item, would be no-op.
-54 Always empty. Use [`andThen()`](#andThen) and [`error()`](#error).
-55 At most one item. Use [`toCompletionStage()`](#toCompletionStage).
-56 Always empty. Use [`andThen()`](#andThen), [`error()`](#error) and [`toCompletionStage()`](#toCompletionStage).
-57 Not supported. Use [`flatMap`](#flatMap) and [`toFlowable()`](#toFlowable).
-58 Use [`flatMap`](#flatMap).
-59 Not supported. Use [`flatMap`](#flatMap) and [`toObservable()`](#toFlowable).
-60 Use [`flatMapSingle`](#flatMapSingle).
-61 Use [`flatMapIterable()`](#flatMapIterable).
-62 Use [`flatMapStream()`](#flatMapStream).
-63 Use [`subscribe()`](#subscribe).
-64 At most one item. Use [`just()`](#just) or [`empty()`](#empty).
-65 Always one item. Use [`just()`](#just).
-66 Always empty. Use [`complete()`](#complete).
-67 Always error.
-68 Use [`wrap()`](#wrap).
-69 Use [`fromSupplier()`](#fromSupplier).
-70 At most one item.
-71 Always empty thus no items to group.
-72 Always empty thus no items to join.
-73 Use [`ignoreElements()`](#ignoreElements).
-74 Use [`ignoreElement()`](#ignoreElement).
-75 At most one item. Use [`timer()`](#timer).
-76 At most one item. Use [`zip()`](#zip)
-77 Always empty thus no items to filter.
-78 Needs backpressure thus not supported outside `Flowable`.
-79 Connectable sources not supported outside `Flowable` and `Observable`. Use a `MaybeSubject`.
-80 Connectable sources not supported outside `Flowable` and `Observable`. Use a `SingleSubject`.
-81 Connectable sources not supported outside `Flowable` and `Observable`. Use a `ConnectableSubject`.
-82 At most one item. Use [`just()`](#just).
-83 At most one item. Use [`map()`](#map).
-84 Always empty thus no items to reduce.
-85 At most one signal type.
-86 At most one item. Use [`takeUntil()`](#takeUntil).
-87 At most one item. Use [`filter()`](#filter).
-88 Use [`startWith()`](#startWith) and [`fromArray()`](#fromArray) of `Flowable` or `Observable`.
-89 Use [`startWith()`](#startWith) and [`just()`](#just) of another reactive type.
-90 Use [`startWith()`](#startWith) and [`fromIterable()`](#fromArray) of `Flowable` or `Observable`.
-91 Always empty. Use [`defaultIfEmpty()`](#defaultIfEmpty).
-92 At most one item. Use [`flatMap()`](#flatMap).
-93 Use [`firstStage`](#firstStage), [`lastStage`](#lastStage) or [`singleStage`](#singleStage).
-94 Would be no-op.
-95 Use [`firstElement`](#firstElement), [`lastElement`](#lastElement) or [`singleElement`](#singleElement).
-96 Use [`firstOrError`](#firstOrError), [`lastOrError`](#lastOrError) or [`singleOrError`](#singleOrError).
-97 Use [`first`](#first), [`last`](#last) or [`single`](#single).
-98 Use [`defaultIfEmpty()`](#defaultIfEmpty).
-99 Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a nested source.
-100 Use [`map()`](#map) to transform into a nested source.
-101 Always empty. Use [`andThen()`](#andThen) to bring in a nested source.
-102 Use [`fromPublisher()`](#fromPublisher).
-103 Use [`merge()`](#merge).
-104 Use [`mergeArray()`](#mergeArray).
-105 Use [`mergeWith()`](#mergeWith).
+28 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapCompletable`](#concatMapCompletable).
+29 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMap`](#concatMap).
+30 At most one item. Use [`flattenAsFlowable`](#flattenAsFlowable) or [`flattenAsObservable`](#flattenAsObservable).
+31 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapMaybe`](#concatMapMaybe).
+32 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapSingle`](#concatMapSingle).
+33 At most one item. Use [`flattenStreamAsFlowable`](#flattenStreamAsFlowable) or [`flattenStreamAsObservable`](#flattenStreamAsObservable).
+34 Never empty thus always 1.
+35 Always empty thus always 0.
+36 At most one item signaled so no subsequent items to work with.
+37 Always empty thus no items to work with.
+38 Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.
+39 At most one item, always distinct.
+40 Different terminology. Use [`doAfterSuccess()`](#doAfterSuccess).
+41 Different terminology. Use [`doAfterNext()`](#doAfterNext).
+42 Different terminology. Use [`doOnDispose()`](#doOnDispose).
+43 Always succeeds or fails, there is no `onComplete` signal.
+44 Different terminology. Use [`doOnCancel()`](#doOnCancel).
+45 At most one item. Use [`doOnEvent()`](#doOnEvent).
+46 Use [`doOnEach()`](#doOnEach).
+47 Different terminology. Use [`doOnSuccess()`](#doOnSuccess).
+48 Backpressure related and not supported outside `Flowable`.
+49 Different terminology. Use [`doOnNext()`](#doOnNext).
+50 At most one item with index 0. Use [`defaultIfEmpty`](#defaultIfEmpty).
+51 Always one item with index 0.
+52 At most one item with index 0. Use [`toSingle`](#toSingle).
+53 Use [`complete()`](#complete).
+54 At most one item. Use [`defaultIfEmpty`](#defaultIfEmpty).
+55 Always one item.
+56 At most one item, would be no-op.
+57 Always one item, would be no-op.
+58 Always empty. Use [`andThen()`](#andThen) and [`error()`](#error).
+59 At most one item. Use [`toCompletionStage()`](#toCompletionStage).
+60 Always empty. Use [`andThen()`](#andThen), [`error()`](#error) and [`toCompletionStage()`](#toCompletionStage).
+61 Use [`flatMap()`](#flatMap).
+62 Not supported. Use [`flatMap`](#flatMap) and [`toFlowable()`](#toFlowable).
+63 Use [`flatMap`](#flatMap).
+64 Not supported. Use [`flatMap`](#flatMap) and [`toObservable()`](#toFlowable).
+65 Use [`flatMapSingle`](#flatMapSingle).
+66 Use [`flatMapIterable()`](#flatMapIterable).
+67 Use [`flatMapStream()`](#flatMapStream).
+68 Use [`subscribe()`](#subscribe).
+69 At most one item. Use [`just()`](#just) or [`empty()`](#empty).
+70 Always one item. Use [`just()`](#just).
+71 Always empty. Use [`complete()`](#complete).
+72 Always error.
+73 Use [`wrap()`](#wrap).
+74 Use [`fromSupplier()`](#fromSupplier).
+75 At most one item.
+76 Always empty thus no items to group.
+77 Always empty thus no items to join.
+78 Use [`ignoreElements()`](#ignoreElements).
+79 Use [`ignoreElement()`](#ignoreElement).
+80 At most one item. Use [`timer()`](#timer).
+81 At most one item. Use [`zip()`](#zip)
+82 Always empty thus no items to filter.
+83 Needs backpressure thus not supported outside `Flowable`.
+84 Connectable sources not supported outside `Flowable` and `Observable`. Use a `MaybeSubject`.
+85 Connectable sources not supported outside `Flowable` and `Observable`. Use a `SingleSubject`.
+86 Connectable sources not supported outside `Flowable` and `Observable`. Use a `ConnectableSubject`.
+87 At most one item. Use [`just()`](#just).
+88 At most one item. Use [`map()`](#map).
+89 Always empty thus no items to reduce.
+90 At most one signal type.
+91 At most one item. Use [`takeUntil()`](#takeUntil).
+92 At most one item. Use [`filter()`](#filter).
+93 Use [`startWith()`](#startWith) and [`fromArray()`](#fromArray) of `Flowable` or `Observable`.
+94 Use [`startWith()`](#startWith) and [`just()`](#just) of another reactive type.
+95 Use [`startWith()`](#startWith) and [`fromIterable()`](#fromArray) of `Flowable` or `Observable`.
+96 Always empty. Use [`defaultIfEmpty()`](#defaultIfEmpty).
+97 At most one item. Use [`flatMap()`](#flatMap).
+98 Use [`firstStage`](#firstStage), [`lastStage`](#lastStage) or [`singleStage`](#singleStage).
+99 Would be no-op.
+100 Use [`firstElement`](#firstElement), [`lastElement`](#lastElement) or [`singleElement`](#singleElement).
+101 Use [`firstOrError`](#firstOrError), [`lastOrError`](#lastOrError) or [`singleOrError`](#singleOrError).
+102 Use [`first`](#first), [`last`](#last) or [`single`](#single).
+103 Use [`defaultIfEmpty()`](#defaultIfEmpty).
+104 Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a nested source.
+105 Use [`map()`](#map) to transform into a nested source.
+106 Always empty. Use [`andThen()`](#andThen) to bring in a nested source.
+107 Use [`fromPublisher()`](#fromPublisher).
+108 Use [`merge()`](#merge).
+109 Use [`mergeArray()`](#mergeArray).
+110 Use [`mergeWith()`](#mergeWith).
+ +#### Under development + +1. Single.concatArrayDelayError() +2. Completable.concatArrayDelayError() +3. Maybe.concatArrayEagerDelayError() +4. Single.concatArrayEagerDelayError() +5. Single.concatDelayError() +6. Completable.concatDelayError() +7. Single.concatMap() +8. Maybe.concatMapCompletable() +9. Single.concatMapCompletable() +10. Maybe.concatMapEager() +11. Single.concatMapEager() +12. Completable.concatMapEager() +13. Maybe.concatMapEagerDelayError() +14. Single.concatMapEagerDelayError() +15. Completable.concatMapEagerDelayError() +16. Maybe.concatMapMaybe() +17. Single.concatMapMaybe() +18. Maybe.concatMapSingle() +19. Single.concatMapSingle() +20. Maybe.dematerialize() +21. Maybe.doOnLifecycle() +22. Single.doOnLifecycle() +23. Completable.doOnLifecycle() +24. Flowable.fromAction() +25. Observable.fromAction() +26. Single.fromAction() +27. Flowable.fromCompletable() +28. Observable.fromCompletable() +29. Flowable.fromMaybe() +30. Observable.fromMaybe() +31. Single.fromMaybe() +32. Flowable.fromObservable() +33. Maybe.fromObservable() +34. Maybe.fromPublisher() +35. Flowable.fromRunnable() +36. Observable.fromRunnable() +37. Single.fromRunnable() +38. Flowable.fromSingle() +39. Observable.fromSingle() +40. Single.mergeArray() +41. Single.mergeArrayDelayError() +42. Single.ofType() +43. Completable.onErrorReturn() +44. Completable.onErrorReturnItem() +45. Single.retryUntil() +46. Completable.retryUntil() +47. Maybe.safeSubscribe() +48. Single.safeSubscribe() +49. Completable.safeSubscribe() +50. Completable.sequenceEqual() +51. Maybe.startWith() +52. Single.startWith() +53. Maybe.switchOnNext() +54. Single.switchOnNext() +55. Completable.switchOnNext() +56. Maybe.switchOnNextDelayError() +57. Single.switchOnNextDelayError() +58. Completable.switchOnNextDelayError() +59. Maybe.timeInterval() +60. Single.timeInterval() +61. Completable.timeInterval() +62. Maybe.timestamp() +63. Single.timestamp() +64. Maybe.toFuture() +65. Completable.toFuture() diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 4a5bd55c39..f0b1f2bea0 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -2105,6 +2105,7 @@ public final Completable onErrorResumeNext(@NonNull FunctionReactiveX operators documentation: Catch + * @since 3.0.0 */ @CheckReturnValue @NonNull diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java index 970d6e36bb..d99202adef 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java @@ -35,6 +35,7 @@ private OperatorMatrixGenerator() { static final String PRESENT = "![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)"; static final String ABSENT = "![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png)"; + static final String TBD = "![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)"; static final Class[] CLASSES = { Flowable.class, Observable.class, Maybe.class, Single.class, Completable.class @@ -81,6 +82,7 @@ public static void main(String[] args) throws IOException { Map notesMap = new HashMap<>(); List notesList = new ArrayList<>(); + List tbdList = new ArrayList<>(); for (String operatorName : sortedOperators) { out.print("`repeatWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `replay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| `retry`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`retryUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`retryUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `retryWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `safeSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| `sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| @@ -201,8 +201,8 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `switchMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `switchMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `switchMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| -`switchOnNextDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`switchOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`switchOnNextDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `take`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| `takeLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| `takeUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -396,24 +396,16 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat 42. Single.ofType() 43. Completable.onErrorReturn() 44. Completable.onErrorReturnItem() -45. Single.retryUntil() -46. Completable.retryUntil() -47. Maybe.safeSubscribe() -48. Single.safeSubscribe() -49. Completable.safeSubscribe() -50. Completable.sequenceEqual() -51. Maybe.startWith() -52. Single.startWith() -53. Maybe.switchOnNext() -54. Single.switchOnNext() -55. Completable.switchOnNext() -56. Maybe.switchOnNextDelayError() -57. Single.switchOnNextDelayError() -58. Completable.switchOnNextDelayError() -59. Maybe.timeInterval() -60. Single.timeInterval() -61. Completable.timeInterval() -62. Maybe.timestamp() -63. Single.timestamp() -64. Maybe.toFuture() -65. Completable.toFuture() +45. Maybe.safeSubscribe() +46. Single.safeSubscribe() +47. Completable.safeSubscribe() +48. Completable.sequenceEqual() +49. Maybe.startWith() +50. Single.startWith() +51. Maybe.timeInterval() +52. Single.timeInterval() +53. Completable.timeInterval() +54. Maybe.timestamp() +55. Single.timestamp() +56. Maybe.toFuture() +57. Completable.toFuture() From ea8ab3bbd5617af2e0f5342c72a42a0eeae941ee Mon Sep 17 00:00:00 2001 From: David Karnok Date: Sat, 25 Jan 2020 16:58:59 +0100 Subject: [PATCH 18/37] 3.x: Add Maybe.dematerialize (#6871) --- .../java/io/reactivex/rxjava3/core/Maybe.java | 41 ++++++ .../io/reactivex/rxjava3/core/Single.java | 2 +- .../operators/maybe/MaybeDematerialize.java | 108 ++++++++++++++++ .../maybe/MaybeDematerializeTest.java | 122 ++++++++++++++++++ 4 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerialize.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerializeTest.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 8699d60e16..a9435534f6 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -2893,6 +2893,47 @@ public final Single defaultIfEmpty(@NonNull T defaultItem) { return RxJavaPlugins.onAssembly(new MaybeToSingle<>(this, defaultItem)); } + /** + * Maps the {@link Notification} success value of the current {@code Maybe} back into normal + * {@code onSuccess}, {@code onError} or {@code onComplete} signals. + *

+ * + *

+ * The intended use of the {@code selector} function is to perform a + * type-safe identity mapping (see example) on a source that is already of type + * {@code Notification}. The Java language doesn't allow + * limiting instance methods to a certain generic argument shape, therefore, + * a function is used to ensure the conversion remains type safe. + *

+ * Regular {@code onError} or {@code onComplete} signals from the current {@code Maybe} are passed along to the downstream. + *

+ *
Scheduler:
+ *
{@code dematerialize} does not operate by default on a particular {@link Scheduler}.
+ *
+ *

+ * Example: + *


+     * Maybe.just(Notification.createOnNext(1))
+     * .dematerialize(notification -> notification)
+     * .test()
+     * .assertResult(1);
+     * 
+ * @param the result type + * @param selector the function called with the success item and should + * return a {@code Notification} instance. + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code selector} is {@code null} + * @since 3.0.0 + * @see #materialize() + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final <@NonNull R> Maybe dematerialize(@NonNull Function> selector) { + Objects.requireNonNull(selector, "selector is null"); + return RxJavaPlugins.onAssembly(new MaybeDematerialize<>(this, selector)); + } + /** * Returns a {@code Maybe} that signals the events emitted by the current {@code Maybe} shifted forward in time by a * specified delay. diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 719719520f..3bfcd78a9c 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -2511,7 +2511,7 @@ public final Single delaySubscription(long time, @NonNull TimeUnit unit, @Non } /** - * Maps the {@link Notification} success value of this {@code Single} back into normal + * Maps the {@link Notification} success value of the current {@code Single} back into normal * {@code onSuccess}, {@code onError} or {@code onComplete} signals as a * {@link Maybe} source. *

diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerialize.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerialize.java new file mode 100644 index 0000000000..d5d3ed25cd --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerialize.java @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; + +import java.util.Objects; + +/** + * Maps the success value of the source to a Notification, then + * maps it back to the corresponding signal type. + *

History: 2.2.4 - experimental + * @param the element type of the source + * @param the element type of the Notification and result + * @since 3.0.0 + */ +public final class MaybeDematerialize extends AbstractMaybeWithUpstream { + + final Function> selector; + + public MaybeDematerialize(Maybe source, Function> selector) { + super(source); + this.selector = selector; + } + + @Override + protected void subscribeActual(MaybeObserver observer) { + source.subscribe(new DematerializeObserver<>(observer, selector)); + } + + static final class DematerializeObserver implements MaybeObserver, Disposable { + + final MaybeObserver downstream; + + final Function> selector; + + Disposable upstream; + + DematerializeObserver(MaybeObserver downstream, + Function> selector) { + this.downstream = downstream; + this.selector = selector; + } + + @Override + public void dispose() { + upstream.dispose(); + } + + @Override + public boolean isDisposed() { + return upstream.isDisposed(); + } + + @Override + public void onSubscribe(Disposable d) { + if (DisposableHelper.validate(upstream, d)) { + upstream = d; + downstream.onSubscribe(this); + } + } + + @Override + public void onSuccess(T t) { + Notification notification; + + try { + notification = Objects.requireNonNull(selector.apply(t), "The selector returned a null Notification"); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + downstream.onError(ex); + return; + } + if (notification.isOnNext()) { + downstream.onSuccess(notification.getValue()); + } else if (notification.isOnComplete()) { + downstream.onComplete(); + } else { + downstream.onError(notification.getError()); + } + } + + @Override + public void onError(Throwable e) { + downstream.onError(e); + } + + @Override + public void onComplete() { + downstream.onComplete(); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerializeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerializeTest.java new file mode 100644 index 0000000000..5c75a92a10 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDematerializeTest.java @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import static org.mockito.Mockito.*; +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.subjects.MaybeSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class MaybeDematerializeTest extends RxJavaTest { + + @Test + public void success() { + Maybe.just(Notification.createOnNext(1)) + .dematerialize(Functions.>identity()) + .test() + .assertResult(1); + } + + @Test + public void empty() { + Maybe.just(Notification.createOnComplete()) + .dematerialize(Functions.>identity()) + .test() + .assertResult(); + } + + @Test + public void emptySource() throws Throwable { + @SuppressWarnings("unchecked") + Function, Notification> function = mock(Function.class); + + Maybe.>empty() + .dematerialize(function) + .test() + .assertResult(); + + verify(function, never()).apply(any()); + } + + @Test + public void error() { + Maybe.>error(new TestException()) + .dematerialize(Functions.>identity()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void errorNotification() { + Maybe.just(Notification.createOnError(new TestException())) + .dematerialize(Functions.>identity()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeMaybe(new Function, MaybeSource>() { + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public MaybeSource apply(Maybe v) throws Exception { + return v.dematerialize((Function)Functions.identity()); + } + }); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(MaybeSubject.>create().dematerialize(Functions.>identity())); + } + + @Test + public void selectorCrash() { + Maybe.just(Notification.createOnNext(1)) + .dematerialize(new Function, Notification>() { + @Override + public Notification apply(Notification v) throws Exception { + throw new TestException(); + } + }) + .test() + .assertFailure(TestException.class); + } + + @Test + public void selectorNull() { + Maybe.just(Notification.createOnNext(1)) + .dematerialize(Functions.justFunction((Notification)null)) + .test() + .assertFailure(NullPointerException.class); + } + + @Test + public void selectorDifferentType() { + Maybe.just(Notification.createOnNext(1)) + .dematerialize(new Function, Notification>() { + @Override + public Notification apply(Notification v) throws Exception { + return Notification.createOnNext("Value-" + 1); + } + }) + .test() + .assertResult("Value-1"); + } +} From 26dacd72f1929c78d84da41ec80dc1ae3996c9f9 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Sat, 25 Jan 2020 22:07:48 +0100 Subject: [PATCH 19/37] 3.x: Add many fromX operators + marbles (#6873) --- docs/Operator-Matrix.md | 67 +++--- .../reactivex/rxjava3/core/Completable.java | 6 +- .../io/reactivex/rxjava3/core/Flowable.java | 209 ++++++++++++++++- .../java/io/reactivex/rxjava3/core/Maybe.java | 61 ++++- .../io/reactivex/rxjava3/core/Observable.java | 130 +++++++++++ .../io/reactivex/rxjava3/core/Single.java | 50 ++++ .../fuseable/AbstractEmptyQueueFuseable.java | 76 ++++++ .../fuseable/CancellableQueueFuseable.java | 42 ++++ .../SubscriberCompletableObserver.java | 59 ----- .../completable/CompletableFromAction.java | 24 +- .../completable/CompletableFromRunnable.java | 24 +- .../completable/CompletableToFlowable.java | 5 +- .../completable/CompletableToObservable.java | 66 +----- .../FlowableElementAtMaybePublisher.java | 42 ++++ .../flowable/FlowableFromAction.java | 68 ++++++ .../flowable/FlowableFromCompletable.java | 86 +++++++ .../flowable/FlowableFromObservable.java | 5 +- .../flowable/FlowableFromRunnable.java | 68 ++++++ .../operators/maybe/MaybeFromCompletable.java | 2 +- .../operators/maybe/MaybeToSingle.java | 2 +- .../observable/ObservableFromAction.java | 66 ++++++ .../observable/ObservableFromCompletable.java | 89 +++++++ .../observable/ObservableFromRunnable.java | 66 ++++++ .../CancellableQueueFuseableTest.java | 75 ++++++ .../CompletableAndThenCompletableabTest.java | 2 +- .../CompletableFromActionTest.java | 16 +- .../CompletableFromRunnableTest.java | 16 +- .../CompletableToObservableTest.java | 38 --- .../flowable/FlowableFromActionTest.java | 214 +++++++++++++++++ .../flowable/FlowableFromCompletableTest.java | 196 ++++++++++++++++ .../flowable/FlowableFromMaybeTest.java | 93 ++++++++ .../flowable/FlowableFromObservableTest.java | 10 + .../flowable/FlowableFromRunnableTest.java | 220 ++++++++++++++++++ .../flowable/FlowableFromSingleTest.java | 86 +++++++ .../maybe/MaybeFromObservableTest.java | 50 ++++ .../maybe/MaybeFromPubisherTest.java | 50 ++++ .../observable/ObservableFromActionTest.java | 214 +++++++++++++++++ .../ObservableFromCompletableTest.java | 195 ++++++++++++++++ .../observable/ObservableFromMaybeTest.java | 93 ++++++++ .../ObservableFromRunnableTest.java | 220 ++++++++++++++++++ .../observable/ObservableFromSingleTest.java | 86 +++++++ .../operators/single/SingleFromMaybeTest.java | 72 ++++++ .../util/OperatorMatrixGenerator.java | 15 ++ .../validators/InternalWrongNaming.java | 5 +- 44 files changed, 3032 insertions(+), 247 deletions(-) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/fuseable/AbstractEmptyQueueFuseable.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseable.java delete mode 100644 src/main/java/io/reactivex/rxjava3/internal/observers/SubscriberCompletableObserver.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybePublisher.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromAction.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletable.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnable.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromAction.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletable.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnable.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromActionTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletableTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromMaybeTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnableTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSingleTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromObservableTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromPubisherTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromActionTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletableTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromMaybeTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnableTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSingleTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromMaybeTest.java diff --git a/docs/Operator-Matrix.md b/docs/Operator-Matrix.md index 3eaaa51221..81e1f7878d 100644 --- a/docs/Operator-Matrix.md +++ b/docs/Operator-Matrix.md @@ -102,19 +102,19 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `flattenStreamAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `forEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))| `forEachWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))| -`fromAction`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromAction`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `fromArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| `fromCallable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromCompletable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))| +`fromCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))| `fromCompletionStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `fromFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `fromIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| -`fromMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `fromOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| -`fromPublisher`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromRunnable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromPublisher`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromRunnable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `fromStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| `fromSupplier`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `generate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| @@ -237,6 +237,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([108](#notes-108))| `zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([109](#notes-109))| `zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([110](#notes-110))| +**237 operators** | **215** | **209** | **108** | **93** | **76** | #### Notes 1 Use [`contains()`](#contains).
@@ -375,37 +376,21 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat 21. Maybe.doOnLifecycle() 22. Single.doOnLifecycle() 23. Completable.doOnLifecycle() -24. Flowable.fromAction() -25. Observable.fromAction() -26. Single.fromAction() -27. Flowable.fromCompletable() -28. Observable.fromCompletable() -29. Flowable.fromMaybe() -30. Observable.fromMaybe() -31. Single.fromMaybe() -32. Flowable.fromObservable() -33. Maybe.fromObservable() -34. Maybe.fromPublisher() -35. Flowable.fromRunnable() -36. Observable.fromRunnable() -37. Single.fromRunnable() -38. Flowable.fromSingle() -39. Observable.fromSingle() -40. Single.mergeArray() -41. Single.mergeArrayDelayError() -42. Single.ofType() -43. Completable.onErrorReturn() -44. Completable.onErrorReturnItem() -45. Maybe.safeSubscribe() -46. Single.safeSubscribe() -47. Completable.safeSubscribe() -48. Completable.sequenceEqual() -49. Maybe.startWith() -50. Single.startWith() -51. Maybe.timeInterval() -52. Single.timeInterval() -53. Completable.timeInterval() -54. Maybe.timestamp() -55. Single.timestamp() -56. Maybe.toFuture() -57. Completable.toFuture() +24. Single.mergeArray() +25. Single.mergeArrayDelayError() +26. Single.ofType() +27. Completable.onErrorReturn() +28. Completable.onErrorReturnItem() +29. Maybe.safeSubscribe() +30. Single.safeSubscribe() +31. Completable.safeSubscribe() +32. Completable.sequenceEqual() +33. Maybe.startWith() +34. Single.startWith() +35. Maybe.timeInterval() +36. Single.timeInterval() +37. Completable.timeInterval() +38. Maybe.timestamp() +39. Single.timestamp() +40. Maybe.toFuture() +41. Completable.toFuture() diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 779d04d1d2..e965855e00 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -496,7 +496,7 @@ public static Completable fromFuture(@NonNull Future future) { } /** - * Returns a {@code Completable} instance that when subscribed to, subscribes to the {@link Maybe} instance and + * Returns a {@code Completable} instance that when subscribed to, subscribes to the {@link MaybeSource} instance and * emits an {@code onComplete} event if the maybe emits {@code onSuccess}/{@code onComplete} or forwards any * {@code onError} events. *

@@ -506,8 +506,8 @@ public static Completable fromFuture(@NonNull Future future) { *

{@code fromMaybe} does not operate by default on a particular {@link Scheduler}.
* *

History: 2.1.17 - beta - * @param the value type of the {@link MaybeSource} element - * @param maybe the {@code Maybe} instance to subscribe to, not {@code null} + * @param the value type of the {@code MaybeSource} element + * @param maybe the {@code MaybeSource} instance to subscribe to, not {@code null} * @return the new {@code Completable} instance * @throws NullPointerException if {@code maybe} is {@code null} * @since 2.2 diff --git a/src/main/java/io/reactivex/rxjava3/core/Flowable.java b/src/main/java/io/reactivex/rxjava3/core/Flowable.java index d1b17e8b84..3d83d477c5 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Flowable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Flowable.java @@ -19,7 +19,6 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; -import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.flowables.*; @@ -28,8 +27,10 @@ import io.reactivex.rxjava3.internal.fuseable.ScalarSupplier; import io.reactivex.rxjava3.internal.jdk8.*; import io.reactivex.rxjava3.internal.operators.flowable.*; +import io.reactivex.rxjava3.internal.operators.maybe.MaybeToFlowable; import io.reactivex.rxjava3.internal.operators.mixed.*; -import io.reactivex.rxjava3.internal.operators.observable.*; +import io.reactivex.rxjava3.internal.operators.observable.ObservableFromPublisher; +import io.reactivex.rxjava3.internal.operators.single.SingleToFlowable; import io.reactivex.rxjava3.internal.schedulers.ImmediateThinScheduler; import io.reactivex.rxjava3.internal.subscribers.*; import io.reactivex.rxjava3.internal.util.*; @@ -1959,6 +1960,39 @@ public static Flowable error(@NonNull Throwable throwable) { return error(Functions.justSupplier(throwable)); } + /** + * Returns a {@code Flowable} instance that runs the given {@link Action} for each subscriber and + * emits either its exception or simply completes. + *

+ * + *

+ *
Backpressure:
+ *
This source doesn't produce any elements and effectively ignores downstream backpressure.
+ *
Scheduler:
+ *
{@code fromAction} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If the {@code Action} throws an exception, the respective {@link Throwable} is + * delivered to the downstream via {@link Subscriber#onError(Throwable)}, + * except when the downstream has canceled the resulting {@code Flowable} source. + * In this latter case, the {@code Throwable} is delivered to the global error handler via + * {@link RxJavaPlugins#onError(Throwable)} as an {@link io.reactivex.rxjava3.exceptions.UndeliverableException UndeliverableException}. + *
+ *
+ * @param the target type + * @param action the {@code Action} to run for each subscriber + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code action} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.PASS_THROUGH) + public static Flowable fromAction(@NonNull Action action) { + Objects.requireNonNull(action, "action is null"); + return RxJavaPlugins.onAssembly(new FlowableFromAction<>(action)); + } + /** * Converts an array into a {@link Publisher} that emits the items in the array. *

@@ -2037,6 +2071,30 @@ public static Flowable error(@NonNull Throwable throwable) { return RxJavaPlugins.onAssembly(new FlowableFromCallable<>(callable)); } + /** + * Wraps a {@link CompletableSource} into a {@code Flowable}. + *

+ * + *

+ *
Backpressure:
+ *
This source doesn't produce any elements and effectively ignores downstream backpressure.
+ *
Scheduler:
+ *
{@code fromCompletable} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the target type + * @param completableSource the {@code CompletableSource} to convert from + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code completableSource} is {@code null} + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.PASS_THROUGH) + public static Flowable fromCompletable(@NonNull CompletableSource completableSource) { + Objects.requireNonNull(completableSource, "completableSource is null"); + return RxJavaPlugins.onAssembly(new FlowableFromCompletable<>(completableSource)); + } + /** * Converts a {@link Future} into a {@link Publisher}. *

@@ -2157,6 +2215,94 @@ public static Flowable error(@NonNull Throwable throwable) { return RxJavaPlugins.onAssembly(new FlowableFromIterable<>(source)); } + /** + * Returns a {@code Flowable} instance that when subscribed to, subscribes to the {@link MaybeSource} instance and + * emits {@code onSuccess} as a single item or forwards any {@code onComplete} or + * {@code onError} signal. + *

+ * + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream.
+ *
Scheduler:
+ *
{@code fromMaybe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the value type of the {@code MaybeSource} element + * @param maybe the {@code MaybeSource} instance to subscribe to, not {@code null} + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code maybe} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public static Flowable fromMaybe(@NonNull MaybeSource maybe) { + Objects.requireNonNull(maybe, "maybe is null"); + return RxJavaPlugins.onAssembly(new MaybeToFlowable<>(maybe)); + } + + /** + * Converts the given {@link ObservableSource} into a {@code Flowable} by applying the specified backpressure strategy. + *

+ * Marble diagrams for the various backpressure strategies are as follows: + *

    + *
  • {@link BackpressureStrategy#BUFFER} + *

    + * + *

  • + *
  • {@link BackpressureStrategy#DROP} + *

    + * + *

  • + *
  • {@link BackpressureStrategy#LATEST} + *

    + * + *

  • + *
  • {@link BackpressureStrategy#ERROR} + *

    + * + *

  • + *
  • {@link BackpressureStrategy#MISSING} + *

    + * + *

  • + *
+ *
+ *
Backpressure:
+ *
The operator applies the chosen backpressure strategy of {@link BackpressureStrategy} enum.
+ *
Scheduler:
+ *
{@code fromObservable} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the element type of the source and resulting sequence + * @param source the {@code ObservableSource} to convert + * @param strategy the backpressure strategy to apply + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code source} or {@code strategy} is {@code null} + */ + @BackpressureSupport(BackpressureKind.SPECIAL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable fromObservable(@NonNull ObservableSource source, @NonNull BackpressureStrategy strategy) { + Objects.requireNonNull(source, "source is null"); + Objects.requireNonNull(strategy, "strategy is null"); + Flowable f = new FlowableFromObservable<>(source); + switch (strategy) { + case DROP: + return f.onBackpressureDrop(); + case LATEST: + return f.onBackpressureLatest(); + case MISSING: + return f; + case ERROR: + return RxJavaPlugins.onAssembly(new FlowableOnBackpressureError<>(f)); + default: + return f.onBackpressureBuffer(); + } + } + /** * Converts an arbitrary Reactive Streams {@link Publisher} into a {@code Flowable} if not already a * {@code Flowable}. @@ -2198,6 +2344,65 @@ public static Flowable fromPublisher(@NonNull Publisher<@NonNull ? extend return RxJavaPlugins.onAssembly(new FlowableFromPublisher<>(publisher)); } + /** + * Returns a {@code Flowable} instance that runs the given {@link Runnable} for each subscriber and + * emits either its exception or simply completes. + *

+ * + *

+ *
Backpressure:
+ *
This source doesn't produce any elements and effectively ignores downstream backpressure.
+ *
Scheduler:
+ *
{@code fromRunnable} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If the {@code Runnable} throws an exception, the respective {@link Throwable} is + * delivered to the downstream via {@link Subscriber#onError(Throwable)}, + * except when the downstream has canceled the resulting {@code Flowable} source. + * In this latter case, the {@code Throwable} is delivered to the global error handler via + * {@link RxJavaPlugins#onError(Throwable)} as an {@link io.reactivex.rxjava3.exceptions.UndeliverableException UndeliverableException}. + *
+ *
+ * @param the target type + * @param run the {@code Runnable} to run for each subscriber + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code run} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.PASS_THROUGH) + public static Flowable fromRunnable(@NonNull Runnable run) { + Objects.requireNonNull(run, "run is null"); + return RxJavaPlugins.onAssembly(new FlowableFromRunnable<>(run)); + } + + /** + * Returns a {@code Flowable} instance that when subscribed to, subscribes to the {@link SingleSource} instance and + * emits {@code onSuccess} as a single item or forwards the {@code onError} signal. + *

+ * + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream.
+ *
Scheduler:
+ *
{@code fromSingle} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the value type of the {@code SingleSource} element + * @param source the {@code SingleSource} instance to subscribe to, not {@code null} + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code source} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public static Flowable fromSingle(@NonNull SingleSource source) { + Objects.requireNonNull(source, "source is null"); + return RxJavaPlugins.onAssembly(new SingleToFlowable<>(source)); + } + /** * Returns a {@code Flowable} that, when a {@link Subscriber} subscribes to it, invokes a supplier function you specify and then * emits the value returned from that function. diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index a9435534f6..12ab3678e2 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -30,6 +30,7 @@ import io.reactivex.rxjava3.internal.operators.flowable.*; import io.reactivex.rxjava3.internal.operators.maybe.*; import io.reactivex.rxjava3.internal.operators.mixed.*; +import io.reactivex.rxjava3.internal.operators.observable.ObservableElementAtMaybe; import io.reactivex.rxjava3.internal.util.ErrorMode; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; @@ -710,7 +711,7 @@ public static Maybe error(@NonNull Supplier supplier } /** - * Returns a {@code Maybe} instance that runs the given {@link Action} for each subscriber and + * Returns a {@code Maybe} instance that runs the given {@link Action} for each observer and * emits either its exception or simply completes. *

* @@ -720,13 +721,13 @@ public static Maybe error(@NonNull Supplier supplier *

Error handling:
*
If the {@code Action} throws an exception, the respective {@link Throwable} is * delivered to the downstream via {@link MaybeObserver#onError(Throwable)}, - * except when the downstream has disposed this {@code Maybe} source. + * except when the downstream has disposed the resulting {@code Maybe} source. * In this latter case, the {@code Throwable} is delivered to the global error handler via * {@link RxJavaPlugins#onError(Throwable)} as an {@link io.reactivex.rxjava3.exceptions.UndeliverableException UndeliverableException}. *
* * @param the target type - * @param action the {@code Action} to run for each subscriber + * @param action the {@code Action} to run for each observer * @return the new {@code Maybe} instance * @throws NullPointerException if {@code action} is {@code null} */ @@ -901,7 +902,57 @@ public static Maybe fromSingle(@NonNull SingleSource single) { } /** - * Returns a {@code Maybe} instance that runs the given {@link Runnable} for each subscriber and + * Wraps an {@link ObservableSource} into a {@code Maybe} and emits the very first item + * or completes if the source is empty. + *

+ * + *

+ *
Scheduler:
+ *
{@code fromObservable} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the target type + * @param source the {@code ObservableSource} to convert from + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code source} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Maybe fromObservable(@NonNull ObservableSource source) { + Objects.requireNonNull(source, "source is null"); + return RxJavaPlugins.onAssembly(new ObservableElementAtMaybe<>(source, 0L)); + } + + /** + * Wraps a {@link Publisher} into a {@code Maybe} and emits the very first item + * or completes if the source is empty. + *

+ * + *

+ *
Backpressure:
+ *
The operator consumes the given {@code Publisher} in an unbounded manner + * (requesting {@link Long#MAX_VALUE}) but cancels it after one item received.
+ *
Scheduler:
+ *
{@code fromPublisher} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the target type + * @param source the {@code Publisher} to convert from + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code source} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.UNBOUNDED_IN) + public static Maybe fromPublisher(@NonNull Publisher source) { + Objects.requireNonNull(source, "source is null"); + return RxJavaPlugins.onAssembly(new FlowableElementAtMaybePublisher<>(source, 0L)); + } + + /** + * Returns a {@code Maybe} instance that runs the given {@link Runnable} for each observer and * emits either its exception or simply completes. *

* @@ -910,7 +961,7 @@ public static Maybe fromSingle(@NonNull SingleSource single) { *

{@code fromRunnable} does not operate by default on a particular {@link Scheduler}.
* * @param the target type - * @param run the {@code Runnable} to run for each subscriber + * @param run the {@code Runnable} to run for each observer * @return the new {@code Maybe} instance * @throws NullPointerException if {@code run} is {@code null} */ diff --git a/src/main/java/io/reactivex/rxjava3/core/Observable.java b/src/main/java/io/reactivex/rxjava3/core/Observable.java index f599ce0eeb..89de9dd63e 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Observable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Observable.java @@ -28,8 +28,10 @@ import io.reactivex.rxjava3.internal.jdk8.*; import io.reactivex.rxjava3.internal.observers.*; import io.reactivex.rxjava3.internal.operators.flowable.*; +import io.reactivex.rxjava3.internal.operators.maybe.MaybeToObservable; import io.reactivex.rxjava3.internal.operators.mixed.*; import io.reactivex.rxjava3.internal.operators.observable.*; +import io.reactivex.rxjava3.internal.operators.single.SingleToObservable; import io.reactivex.rxjava3.internal.util.*; import io.reactivex.rxjava3.observables.*; import io.reactivex.rxjava3.observers.*; @@ -1734,6 +1736,36 @@ public static Observable error(@NonNull Throwable throwable) { return error(Functions.justSupplier(throwable)); } + /** + * Returns an {@code Observable} instance that runs the given {@link Action} for each subscriber and + * emits either its exception or simply completes. + *

+ * + *

+ *
Scheduler:
+ *
{@code fromAction} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If the {@code Action} throws an exception, the respective {@link Throwable} is + * delivered to the downstream via {@link Observer#onError(Throwable)}, + * except when the downstream has canceled the resulting {@code Observable} source. + * In this latter case, the {@code Throwable} is delivered to the global error handler via + * {@link RxJavaPlugins#onError(Throwable)} as an {@link io.reactivex.rxjava3.exceptions.UndeliverableException UndeliverableException}. + *
+ *
+ * @param the target type + * @param action the {@code Action} to run for each subscriber + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code action} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Observable fromAction(@NonNull Action action) { + Objects.requireNonNull(action, "action is null"); + return RxJavaPlugins.onAssembly(new ObservableFromAction<>(action)); + } + /** * Converts an array into an {@link ObservableSource} that emits the items in the array. *

@@ -1804,6 +1836,27 @@ public static Observable fromCallable(@NonNull Callable call return RxJavaPlugins.onAssembly(new ObservableFromCallable<>(callable)); } + /** + * Wraps a {@link CompletableSource} into an {@code Observable}. + *

+ * + *

+ *
Scheduler:
+ *
{@code fromCompletable} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the target type + * @param completableSource the {@code CompletableSource} to convert from + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code completableSource} is {@code null} + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Observable fromCompletable(@NonNull CompletableSource completableSource) { + Objects.requireNonNull(completableSource, "completableSource is null"); + return RxJavaPlugins.onAssembly(new ObservableFromCompletable<>(completableSource)); + } + /** * Converts a {@link Future} into an {@code Observable}. *

@@ -1912,6 +1965,30 @@ public static Observable fromIterable(@NonNull Iterable<@NonNull ? extend return RxJavaPlugins.onAssembly(new ObservableFromIterable<>(source)); } + /** + * Returns an {@code Observable} instance that when subscribed to, subscribes to the {@link MaybeSource} instance and + * emits {@code onSuccess} as a single item or forwards any {@code onComplete} or + * {@code onError} signal. + *

+ * + *

+ *
Scheduler:
+ *
{@code fromMaybe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the value type of the {@code MaybeSource} element + * @param maybe the {@code MaybeSource} instance to subscribe to, not {@code null} + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code maybe} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Observable fromMaybe(@NonNull MaybeSource maybe) { + Objects.requireNonNull(maybe, "maybe is null"); + return RxJavaPlugins.onAssembly(new MaybeToObservable<>(maybe)); + } + /** * Converts an arbitrary Reactive Streams {@link Publisher} into an {@code Observable}. *

@@ -1949,6 +2026,59 @@ public static Observable fromPublisher(@NonNull Publisher<@NonNull ? exte return RxJavaPlugins.onAssembly(new ObservableFromPublisher<>(publisher)); } + /** + * Returns an {@code Observable} instance that runs the given {@link Runnable} for each observer and + * emits either its exception or simply completes. + *

+ * + *

+ *
Scheduler:
+ *
{@code fromRunnable} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If the {@code Runnable} throws an exception, the respective {@link Throwable} is + * delivered to the downstream via {@link Observer#onError(Throwable)}, + * except when the downstream has canceled the resulting {@code Observable} source. + * In this latter case, the {@code Throwable} is delivered to the global error handler via + * {@link RxJavaPlugins#onError(Throwable)} as an {@link io.reactivex.rxjava3.exceptions.UndeliverableException UndeliverableException}. + *
+ *
+ * @param the target type + * @param run the {@code Runnable} to run for each observer + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code run} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Observable fromRunnable(@NonNull Runnable run) { + Objects.requireNonNull(run, "run is null"); + return RxJavaPlugins.onAssembly(new ObservableFromRunnable<>(run)); + } + + /** + * Returns an {@code Observable} instance that when subscribed to, subscribes to the {@link SingleSource} instance and + * emits {@code onSuccess} as a single item or forwards the {@code onError} signal. + *

+ * + *

+ *
Scheduler:
+ *
{@code fromSingle} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the value type of the {@code SingleSource} element + * @param source the {@code SingleSource} instance to subscribe to, not {@code null} + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code source} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Observable fromSingle(@NonNull SingleSource source) { + Objects.requireNonNull(source, "source is null"); + return RxJavaPlugins.onAssembly(new SingleToObservable<>(source)); + } + /** * Returns an {@code Observable} that, when an observer subscribes to it, invokes a supplier function you specify and then * emits the value returned from that function. diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 3bfcd78a9c..a3b536b1f7 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -731,6 +731,56 @@ public static Single error(@NonNull Throwable throwable) { return toSingle(Flowable.fromFuture(future, timeout, unit)); } + /** + * Returns a {@code Single} instance that when subscribed to, subscribes to the {@link MaybeSource} instance and + * emits {@code onSuccess} as a single item, turns an {@code onComplete} into {@link NoSuchElementException} error signal or + * forwards the {@code onError} signal. + *

+ * + *

+ *
Scheduler:
+ *
{@code fromMaybe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the value type of the {@code MaybeSource} element + * @param maybe the {@code MaybeSource} instance to subscribe to, not {@code null} + * @return the new {@code Single} instance + * @throws NullPointerException if {@code maybe} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Single fromMaybe(@NonNull MaybeSource maybe) { + Objects.requireNonNull(maybe, "maybe is null"); + return RxJavaPlugins.onAssembly(new MaybeToSingle<>(maybe, null)); + } + + /** + * Returns a {@code Single} instance that when subscribed to, subscribes to the {@link MaybeSource} instance and + * emits {@code onSuccess} as a single item, emits the {@code defaultItem} for an {@code onComplete} signal or + * forwards the {@code onError} signal. + *

+ * + *

+ *
Scheduler:
+ *
{@code fromMaybe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the value type of the {@code MaybeSource} element + * @param maybe the {@code MaybeSource} instance to subscribe to, not {@code null} + * @param defaultItem the item to signal if the current {@code MaybeSource} is empty + * @return the new {@code Single} instance + * @throws NullPointerException if {@code maybe} or {@code defaultItem} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Single fromMaybe(@NonNull MaybeSource maybe, @NonNull T defaultItem) { + Objects.requireNonNull(maybe, "maybe is null"); + Objects.requireNonNull(defaultItem, "defaultItem is null"); + return RxJavaPlugins.onAssembly(new MaybeToSingle<>(maybe, defaultItem)); + } + /** * Wraps a specific {@link Publisher} into a {@code Single} and signals its single element or error. *

diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/AbstractEmptyQueueFuseable.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/AbstractEmptyQueueFuseable.java new file mode 100644 index 0000000000..071db9fff8 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/AbstractEmptyQueueFuseable.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.fuseable; + +import io.reactivex.rxjava3.annotations.NonNull; + +/** + * Represents an empty, async-only {@link QueueFuseable} instance. + * + * @param the output value type + * @since 3.0.0 + */ +public abstract class AbstractEmptyQueueFuseable +implements QueueSubscription, QueueDisposable { + + @Override + public final int requestFusion(int mode) { + return mode & ASYNC; + } + + @Override + public final boolean offer(@NonNull T value) { + throw new UnsupportedOperationException("Should not be called!"); + } + + @Override + public final boolean offer(@NonNull T v1, @NonNull T v2) { + throw new UnsupportedOperationException("Should not be called!"); + } + + @Override + public final T poll() throws Throwable { + return null; // always empty + } + + @Override + public final boolean isEmpty() { + return true; // always empty + } + + @Override + public final void clear() { + // always empty + } + + @Override + public final void request(long n) { + // no items to request + } + + @Override + public void cancel() { + // default No-op + } + + @Override + public void dispose() { + // default No-op + } + + @Override + public boolean isDisposed() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseable.java b/src/main/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseable.java new file mode 100644 index 0000000000..8f9e12d3cb --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseable.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.fuseable; + +/** + * Represents an empty, async-only {@link QueueFuseable} instance that tracks and exposes a + * canceled/disposed state. + * + * @param the output value type + * @since 3.0.0 + */ +public final class CancellableQueueFuseable +extends AbstractEmptyQueueFuseable { + + volatile boolean disposed; + + @Override + public void cancel() { + disposed = true; + } + + @Override + public void dispose() { + disposed = true; + } + + @Override + public boolean isDisposed() { + return disposed; + } +} \ No newline at end of file diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/SubscriberCompletableObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/SubscriberCompletableObserver.java deleted file mode 100644 index 2bbc5128d6..0000000000 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/SubscriberCompletableObserver.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2016-present, RxJava Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See - * the License for the specific language governing permissions and limitations under the License. - */ - -package io.reactivex.rxjava3.internal.observers; - -import org.reactivestreams.*; - -import io.reactivex.rxjava3.core.CompletableObserver; -import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.internal.disposables.DisposableHelper; - -public final class SubscriberCompletableObserver implements CompletableObserver, Subscription { - final Subscriber subscriber; - - Disposable upstream; - - public SubscriberCompletableObserver(Subscriber subscriber) { - this.subscriber = subscriber; - } - - @Override - public void onComplete() { - subscriber.onComplete(); - } - - @Override - public void onError(Throwable e) { - subscriber.onError(e); - } - - @Override - public void onSubscribe(Disposable d) { - if (DisposableHelper.validate(this.upstream, d)) { - this.upstream = d; - - subscriber.onSubscribe(this); - } - } - - @Override - public void request(long n) { - // ignored, no values emitted anyway - } - - @Override - public void cancel() { - upstream.dispose(); - } -} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromAction.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromAction.java index 4cd7fb479c..82bec67c92 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromAction.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromAction.java @@ -31,19 +31,21 @@ public CompletableFromAction(Action run) { protected void subscribeActual(CompletableObserver observer) { Disposable d = Disposable.empty(); observer.onSubscribe(d); - try { - run.run(); - } catch (Throwable e) { - Exceptions.throwIfFatal(e); + if (!d.isDisposed()) { + try { + run.run(); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + if (!d.isDisposed()) { + observer.onError(e); + } else { + RxJavaPlugins.onError(e); + } + return; + } if (!d.isDisposed()) { - observer.onError(e); - } else { - RxJavaPlugins.onError(e); + observer.onComplete(); } - return; - } - if (!d.isDisposed()) { - observer.onComplete(); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnable.java index e94d650310..60332d8db2 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnable.java @@ -30,19 +30,21 @@ public CompletableFromRunnable(Runnable runnable) { protected void subscribeActual(CompletableObserver observer) { Disposable d = Disposable.empty(); observer.onSubscribe(d); - try { - runnable.run(); - } catch (Throwable e) { - Exceptions.throwIfFatal(e); + if (!d.isDisposed()) { + try { + runnable.run(); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + if (!d.isDisposed()) { + observer.onError(e); + } else { + RxJavaPlugins.onError(e); + } + return; + } if (!d.isDisposed()) { - observer.onError(e); - } else { - RxJavaPlugins.onError(e); + observer.onComplete(); } - return; - } - if (!d.isDisposed()) { - observer.onComplete(); } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowable.java index 9ad0d0a8d8..9a6c0326a1 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFlowable.java @@ -16,7 +16,7 @@ import org.reactivestreams.Subscriber; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.internal.observers.SubscriberCompletableObserver; +import io.reactivex.rxjava3.internal.operators.flowable.FlowableFromCompletable; public final class CompletableToFlowable extends Flowable { @@ -28,7 +28,6 @@ public CompletableToFlowable(CompletableSource source) { @Override protected void subscribeActual(Subscriber s) { - SubscriberCompletableObserver os = new SubscriberCompletableObserver<>(s); - source.subscribe(os); + source.subscribe(new FlowableFromCompletable.FromCompletableObserver<>(s)); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservable.java index 095a975dbf..84eea97c8d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservable.java @@ -14,9 +14,7 @@ package io.reactivex.rxjava3.internal.operators.completable; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.internal.disposables.DisposableHelper; -import io.reactivex.rxjava3.internal.observers.BasicQueueDisposable; +import io.reactivex.rxjava3.internal.operators.observable.ObservableFromCompletable; /** * Wraps a Completable and exposes it as an Observable. @@ -33,66 +31,6 @@ public CompletableToObservable(CompletableSource source) { @Override protected void subscribeActual(Observer observer) { - source.subscribe(new ObserverCompletableObserver(observer)); - } - - static final class ObserverCompletableObserver extends BasicQueueDisposable - implements CompletableObserver { - - final Observer observer; - - Disposable upstream; - - ObserverCompletableObserver(Observer observer) { - this.observer = observer; - } - - @Override - public void onComplete() { - observer.onComplete(); - } - - @Override - public void onError(Throwable e) { - observer.onError(e); - } - - @Override - public void onSubscribe(Disposable d) { - if (DisposableHelper.validate(upstream, d)) { - this.upstream = d; - observer.onSubscribe(this); - } - } - - @Override - public int requestFusion(int mode) { - return mode & ASYNC; - } - - @Override - public Void poll() { - return null; // always empty - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public void clear() { - // always empty - } - - @Override - public void dispose() { - upstream.dispose(); - } - - @Override - public boolean isDisposed() { - return upstream.isDisposed(); - } + source.subscribe(new ObservableFromCompletable.FromCompletableObserver<>(observer)); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybePublisher.java new file mode 100644 index 0000000000..a474b03280 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableElementAtMaybePublisher.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import org.reactivestreams.Publisher; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.internal.operators.flowable.FlowableElementAtMaybe.ElementAtSubscriber; + +/** + * Emits the indexth element from a Publisher as a Maybe. + * + * @param the element type of the source + * @since 3.0.0 + */ +public final class FlowableElementAtMaybePublisher extends Maybe { + + final Publisher source; + + final long index; + + public FlowableElementAtMaybePublisher(Publisher source, long index) { + this.source = source; + this.index = index; + } + + @Override + protected void subscribeActual(MaybeObserver observer) { + source.subscribe(new ElementAtSubscriber<>(observer, index)); + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromAction.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromAction.java new file mode 100644 index 0000000000..2d683e7601 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromAction.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import org.reactivestreams.Subscriber; + +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.fuseable.CancellableQueueFuseable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Executes an {@link Action} and signals its exception or completes normally. + * + * @param the value type + * @since 3.0.0 + */ +public final class FlowableFromAction extends Flowable implements Supplier { + + final Action action; + + public FlowableFromAction(Action action) { + this.action = action; + } + + @Override + protected void subscribeActual(Subscriber subscriber) { + CancellableQueueFuseable qs = new CancellableQueueFuseable<>(); + subscriber.onSubscribe(qs); + + if (!qs.isDisposed()) { + + try { + action.run(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + if (!qs.isDisposed()) { + subscriber.onError(ex); + } else { + RxJavaPlugins.onError(ex); + } + return; + } + + if (!qs.isDisposed()) { + subscriber.onComplete(); + } + } + } + + @Override + public T get() throws Throwable { + action.run(); + return null; // considered as onComplete() + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletable.java new file mode 100644 index 0000000000..78b37325ca --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletable.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import org.reactivestreams.Subscriber; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; +import io.reactivex.rxjava3.internal.fuseable.*; + +/** + * Wrap a Completable into a Flowable. + * + * @param the value type + * @since 3.0.0 + */ +public final class FlowableFromCompletable extends Flowable implements HasUpstreamCompletableSource { + + final CompletableSource source; + + public FlowableFromCompletable(CompletableSource source) { + this.source = source; + } + + @Override + public CompletableSource source() { + return source; + } + + @Override + protected void subscribeActual(Subscriber observer) { + source.subscribe(new FromCompletableObserver(observer)); + } + + public static final class FromCompletableObserver + extends AbstractEmptyQueueFuseable + implements CompletableObserver { + + final Subscriber downstream; + + Disposable upstream; + + public FromCompletableObserver(Subscriber downstream) { + this.downstream = downstream; + } + + @Override + public void cancel() { + upstream.dispose(); + upstream = DisposableHelper.DISPOSED; + } + + @Override + public void onSubscribe(Disposable d) { + if (DisposableHelper.validate(this.upstream, d)) { + this.upstream = d; + + downstream.onSubscribe(this); + } + } + + @Override + public void onComplete() { + upstream = DisposableHelper.DISPOSED; + downstream.onComplete(); + } + + @Override + public void onError(Throwable e) { + upstream = DisposableHelper.DISPOSED; + downstream.onError(e); + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservable.java index 105c6b6ee2..459228f549 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservable.java @@ -18,9 +18,10 @@ import io.reactivex.rxjava3.disposables.Disposable; public final class FlowableFromObservable extends Flowable { - private final Observable upstream; - public FlowableFromObservable(Observable upstream) { + private final ObservableSource upstream; + + public FlowableFromObservable(ObservableSource upstream) { this.upstream = upstream; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnable.java new file mode 100644 index 0000000000..b163f1b7ee --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnable.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import org.reactivestreams.Subscriber; + +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.Supplier; +import io.reactivex.rxjava3.internal.fuseable.CancellableQueueFuseable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Executes an {@link Runnable} and signals its exception or completes normally. + * + * @param the value type + * @since 3.0.0 + */ +public final class FlowableFromRunnable extends Flowable implements Supplier { + + final Runnable run; + + public FlowableFromRunnable(Runnable run) { + this.run = run; + } + + @Override + protected void subscribeActual(Subscriber subscriber) { + CancellableQueueFuseable qs = new CancellableQueueFuseable<>(); + subscriber.onSubscribe(qs); + + if (!qs.isDisposed()) { + + try { + run.run(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + if (!qs.isDisposed()) { + subscriber.onError(ex); + } else { + RxJavaPlugins.onError(ex); + } + return; + } + + if (!qs.isDisposed()) { + subscriber.onComplete(); + } + } + } + + @Override + public T get() throws Throwable { + run.run(); + return null; // considered as onComplete() + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletable.java index bdbc2ec03b..5cb73e821c 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromCompletable.java @@ -19,7 +19,7 @@ import io.reactivex.rxjava3.internal.fuseable.HasUpstreamCompletableSource; /** - * Wrap a Single into a Maybe. + * Wrap a Completable into a Maybe. * * @param the value type */ diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingle.java index 3199521639..807b9cac51 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToSingle.java @@ -22,7 +22,7 @@ /** * Wraps a MaybeSource and exposes its onSuccess and onError signals and signals - * NoSuchElementException for onComplete. + * NoSuchElementException for onComplete if {@code defaultValue} is null. * * @param the value type */ diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromAction.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromAction.java new file mode 100644 index 0000000000..cccb5b5d38 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromAction.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.fuseable.CancellableQueueFuseable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Executes an {@link Action} and signals its exception or completes normally. + * + * @param the value type + * @since 3.0.0 + */ +public final class ObservableFromAction extends Observable implements Supplier { + + final Action action; + + public ObservableFromAction(Action action) { + this.action = action; + } + + @Override + protected void subscribeActual(Observer observer) { + CancellableQueueFuseable qs = new CancellableQueueFuseable<>(); + observer.onSubscribe(qs); + + if (!qs.isDisposed()) { + + try { + action.run(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + if (!qs.isDisposed()) { + observer.onError(ex); + } else { + RxJavaPlugins.onError(ex); + } + return; + } + + if (!qs.isDisposed()) { + observer.onComplete(); + } + } + } + + @Override + public T get() throws Throwable { + action.run(); + return null; // considered as onComplete() + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletable.java new file mode 100644 index 0000000000..4748e6a625 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletable.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; +import io.reactivex.rxjava3.internal.fuseable.*; + +/** + * Wrap a Completable into an Observable. + * + * @param the value type + * @since 3.0.0 + */ +public final class ObservableFromCompletable extends Observable implements HasUpstreamCompletableSource { + + final CompletableSource source; + + public ObservableFromCompletable(CompletableSource source) { + this.source = source; + } + + @Override + public CompletableSource source() { + return source; + } + + @Override + protected void subscribeActual(Observer observer) { + source.subscribe(new FromCompletableObserver(observer)); + } + + public static final class FromCompletableObserver + extends AbstractEmptyQueueFuseable + implements CompletableObserver { + + final Observer downstream; + + Disposable upstream; + + public FromCompletableObserver(Observer downstream) { + this.downstream = downstream; + } + + @Override + public void dispose() { + upstream.dispose(); + upstream = DisposableHelper.DISPOSED; + } + + @Override + public boolean isDisposed() { + return upstream.isDisposed(); + } + + @Override + public void onSubscribe(Disposable d) { + if (DisposableHelper.validate(this.upstream, d)) { + this.upstream = d; + + downstream.onSubscribe(this); + } + } + + @Override + public void onComplete() { + upstream = DisposableHelper.DISPOSED; + downstream.onComplete(); + } + + @Override + public void onError(Throwable e) { + upstream = DisposableHelper.DISPOSED; + downstream.onError(e); + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnable.java new file mode 100644 index 0000000000..0dc37a8993 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnable.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.Supplier; +import io.reactivex.rxjava3.internal.fuseable.CancellableQueueFuseable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Executes an {@link Runnable} and signals its exception or completes normally. + * + * @param the value type + * @since 3.0.0 + */ +public final class ObservableFromRunnable extends Observable implements Supplier { + + final Runnable run; + + public ObservableFromRunnable(Runnable run) { + this.run = run; + } + + @Override + protected void subscribeActual(Observer observer) { + CancellableQueueFuseable qs = new CancellableQueueFuseable<>(); + observer.onSubscribe(qs); + + if (!qs.isDisposed()) { + + try { + run.run(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + if (!qs.isDisposed()) { + observer.onError(ex); + } else { + RxJavaPlugins.onError(ex); + } + return; + } + + if (!qs.isDisposed()) { + observer.onComplete(); + } + } + } + + @Override + public T get() throws Throwable { + run.run(); + return null; // considered as onComplete() + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java b/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java new file mode 100644 index 0000000000..ed4718fd1c --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.fuseable; + +import static org.junit.Assert.*; +import org.junit.Test; + +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class CancellableQueueFuseableTest { + + @Test + public void offer() { + TestHelper.assertNoOffer(new CancellableQueueFuseable<>()); + } + + @Test + public void cancel() { + CancellableQueueFuseable qs = new CancellableQueueFuseable<>(); + + assertFalse(qs.isDisposed()); + + qs.cancel(); + + assertTrue(qs.isDisposed()); + + qs.cancel(); + + assertTrue(qs.isDisposed()); + } + + @Test + public void dispose() { + CancellableQueueFuseable qs = new CancellableQueueFuseable<>(); + + assertFalse(qs.isDisposed()); + + qs.dispose(); + + assertTrue(qs.isDisposed()); + + qs.dispose(); + + assertTrue(qs.isDisposed()); + } + + @Test + public void cancel2() { + AbstractEmptyQueueFuseable qs = new AbstractEmptyQueueFuseable() {}; + + assertFalse(qs.isDisposed()); + + qs.cancel(); + } + + @Test + public void dispose2() { + AbstractEmptyQueueFuseable qs = new AbstractEmptyQueueFuseable() {}; + + assertFalse(qs.isDisposed()); + + qs.dispose(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletableabTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletableabTest.java index a98f3b5abb..051dd4e364 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletableabTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableAndThenCompletableabTest.java @@ -102,7 +102,7 @@ public void run() { .andThen(Completable.complete()) .test(true) .assertEmpty(); - assertEquals(1, completableRunCount.get()); + assertEquals(0, completableRunCount.get()); } @Test diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromActionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromActionTest.java index 56354fc448..1f4df16f44 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromActionTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromActionTest.java @@ -14,6 +14,7 @@ package io.reactivex.rxjava3.internal.operators.completable; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; import java.util.concurrent.atomic.AtomicInteger; @@ -108,7 +109,7 @@ public void run() throws Exception { .test(true) .assertEmpty(); - assertEquals(1, calls.get()); + assertEquals(0, calls.get()); } @Test @@ -124,6 +125,17 @@ public void run() throws Exception { .test(true) .assertEmpty(); - assertEquals(1, calls.get()); + assertEquals(0, calls.get()); + } + + @Test + public void disposedUpfront() throws Throwable { + Action run = mock(Action.class); + + Completable.fromAction(run) + .test(true) + .assertEmpty(); + + verify(run, never()).run(); } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnableTest.java index 5d6473077f..2559f09187 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableFromRunnableTest.java @@ -14,6 +14,7 @@ package io.reactivex.rxjava3.internal.operators.completable; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; import java.util.concurrent.atomic.AtomicInteger; @@ -107,7 +108,7 @@ public void run() { .test(true) .assertEmpty(); - assertEquals(1, calls.get()); + assertEquals(0, calls.get()); } @Test @@ -123,6 +124,17 @@ public void run() { .test(true) .assertEmpty(); - assertEquals(1, calls.get()); + assertEquals(0, calls.get()); + } + + @Test + public void disposedUpfront() throws Throwable { + Runnable run = mock(Runnable.class); + + Completable.fromRunnable(run) + .test(true) + .assertEmpty(); + + verify(run, never()).run(); } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservableTest.java index f1bbda0353..96404e8167 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToObservableTest.java @@ -13,16 +13,10 @@ package io.reactivex.rxjava3.internal.operators.completable; -import static org.junit.Assert.*; - import org.junit.Test; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.*; import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; -import io.reactivex.rxjava3.internal.operators.completable.CompletableToObservable.ObserverCompletableObserver; -import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.testsupport.TestHelper; public class CompletableToObservableTest extends RxJavaTest { @@ -37,36 +31,4 @@ public Observable apply(Completable c) throws Exception { }); } - @Test - public void fusion() throws Exception { - TestObserver to = new TestObserver<>(); - - ObserverCompletableObserver co = new ObserverCompletableObserver(to); - - Disposable d = Disposable.empty(); - - co.onSubscribe(d); - - assertEquals(QueueFuseable.NONE, co.requestFusion(QueueFuseable.SYNC)); - - assertEquals(QueueFuseable.ASYNC, co.requestFusion(QueueFuseable.ASYNC)); - - assertEquals(QueueFuseable.ASYNC, co.requestFusion(QueueFuseable.ANY)); - - assertTrue(co.isEmpty()); - - assertNull(co.poll()); - - co.clear(); - - assertFalse(co.isDisposed()); - - co.dispose(); - - assertTrue(d.isDisposed()); - - assertTrue(co.isDisposed()); - - TestHelper.assertNoOffer(co); - } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromActionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromActionTest.java new file mode 100644 index 0000000000..b19a03159c --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromActionTest.java @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subscribers.TestSubscriber; +import io.reactivex.rxjava3.testsupport.*; + +public class FlowableFromActionTest extends RxJavaTest { + @Test + public void fromAction() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Flowable.fromAction(new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + }) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromActionTwice() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Action run = new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + }; + + Flowable.fromAction(run) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + + Flowable.fromAction(run) + .test() + .assertResult(); + + assertEquals(2, atomicInteger.get()); + } + + @Test + public void fromActionInvokesLazy() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Flowable source = Flowable.fromAction(new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + }); + + assertEquals(0, atomicInteger.get()); + + source + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromActionThrows() { + Flowable.fromAction(new Action() { + @Override + public void run() throws Exception { + throw new UnsupportedOperationException(); + } + }) + .test() + .assertFailure(UnsupportedOperationException.class); + } + + @SuppressWarnings("unchecked") + @Test + public void callable() throws Throwable { + final int[] counter = { 0 }; + + Flowable m = Flowable.fromAction(new Action() { + @Override + public void run() throws Exception { + counter[0]++; + } + }); + + assertTrue(m.getClass().toString(), m instanceof Supplier); + + assertNull(((Supplier)m).get()); + + assertEquals(1, counter[0]); + } + + @Test + public void noErrorLoss() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + final CountDownLatch cdl1 = new CountDownLatch(1); + final CountDownLatch cdl2 = new CountDownLatch(1); + + TestSubscriber ts = Flowable.fromAction(new Action() { + @Override + public void run() throws Exception { + cdl1.countDown(); + cdl2.await(5, TimeUnit.SECONDS); + } + }).subscribeOn(Schedulers.single()).test(); + + assertTrue(cdl1.await(5, TimeUnit.SECONDS)); + + ts.cancel(); + + int timeout = 10; + + while (timeout-- > 0 && errors.isEmpty()) { + Thread.sleep(100); + } + + TestHelper.assertUndeliverable(errors, 0, InterruptedException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void disposedUpfront() throws Throwable { + Action run = mock(Action.class); + + Flowable.fromAction(run) + .test(1L, true) + .assertEmpty(); + + verify(run, never()).run(); + } + + @Test + public void cancelWhileRunning() { + final TestSubscriber ts = new TestSubscriber<>(); + + Flowable.fromAction(new Action() { + @Override + public void run() throws Exception { + ts.cancel(); + } + }) + .subscribeWith(ts) + .assertEmpty(); + + assertTrue(ts.isCancelled()); + } + + @Test + public void asyncFused() throws Throwable { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ASYNC); + + Action action = mock(Action.class); + + Flowable.fromAction(action) + .subscribe(ts); + + ts.assertFusionMode(QueueFuseable.ASYNC) + .assertResult(); + + verify(action).run(); + } + + @Test + public void syncFusedRejected() throws Throwable { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.SYNC); + + Action action = mock(Action.class); + + Flowable.fromAction(action) + .subscribe(ts); + + ts.assertFusionMode(QueueFuseable.NONE) + .assertResult(); + + verify(action).run(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletableTest.java new file mode 100644 index 0000000000..47c0b815fb --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromCompletableTest.java @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subscribers.TestSubscriber; +import io.reactivex.rxjava3.testsupport.*; + +public class FlowableFromCompletableTest extends RxJavaTest { + @Test + public void fromCompletable() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Flowable.fromCompletable(Completable.fromAction(new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + })) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromCompletableTwice() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Action run = new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + }; + + Flowable.fromCompletable(Completable.fromAction(run)) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + + Flowable.fromCompletable(Completable.fromAction(run)) + .test() + .assertResult(); + + assertEquals(2, atomicInteger.get()); + } + + @Test + public void fromCompletableInvokesLazy() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Flowable source = Flowable.fromCompletable(Completable.fromAction(new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + })); + + assertEquals(0, atomicInteger.get()); + + source + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromCompletableThrows() { + Flowable.fromCompletable(Completable.fromAction(new Action() { + @Override + public void run() throws Exception { + throw new UnsupportedOperationException(); + } + })) + .test() + .assertFailure(UnsupportedOperationException.class); + } + + @Test + public void noErrorLoss() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + final CountDownLatch cdl1 = new CountDownLatch(1); + final CountDownLatch cdl2 = new CountDownLatch(1); + + TestSubscriber ts = Flowable.fromCompletable(Completable.fromAction(new Action() { + @Override + public void run() throws Exception { + cdl1.countDown(); + cdl2.await(5, TimeUnit.SECONDS); + } + })) + .subscribeOn(Schedulers.single()).test(); + + assertTrue(cdl1.await(5, TimeUnit.SECONDS)); + + ts.cancel(); + + int timeout = 10; + + while (timeout-- > 0 && errors.isEmpty()) { + Thread.sleep(100); + } + + TestHelper.assertUndeliverable(errors, 0, InterruptedException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void disposedUpfront() throws Throwable { + Action run = mock(Action.class); + + Flowable.fromCompletable(Completable.fromAction(run)) + .test(1L, true) + .assertEmpty(); + + verify(run, never()).run(); + } + + @Test + public void cancelWhileRunning() { + final TestSubscriber ts = new TestSubscriber<>(); + + Flowable.fromCompletable(Completable.fromAction(new Action() { + @Override + public void run() throws Exception { + ts.cancel(); + } + })) + .subscribeWith(ts) + .assertEmpty(); + + assertTrue(ts.isCancelled()); + } + + @Test + public void asyncFused() throws Throwable { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ASYNC); + + Action action = mock(Action.class); + + Flowable.fromCompletable(Completable.fromAction(action)) + .subscribe(ts); + + ts.assertFusionMode(QueueFuseable.ASYNC) + .assertResult(); + + verify(action).run(); + } + + @Test + public void syncFusedRejected() throws Throwable { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.SYNC); + + Action action = mock(Action.class); + + Flowable.fromCompletable(Completable.fromAction(action)) + .subscribe(ts); + + ts.assertFusionMode(QueueFuseable.NONE) + .assertResult(); + + verify(action).run(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromMaybeTest.java new file mode 100644 index 0000000000..5eca34f9cb --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromMaybeTest.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.subjects.MaybeSubject; +import io.reactivex.rxjava3.subscribers.TestSubscriber; +import io.reactivex.rxjava3.testsupport.TestSubscriberEx; + +public class FlowableFromMaybeTest extends RxJavaTest { + + @Test + public void success() { + Flowable.fromMaybe(Maybe.just(1).hide()) + .test() + .assertResult(1); + } + + @Test + public void empty() { + Flowable.fromMaybe(Maybe.empty().hide()) + .test() + .assertResult(); + } + + @Test + public void error() { + Flowable.fromMaybe(Maybe.error(new TestException()).hide()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void cancelComposes() { + MaybeSubject ms = MaybeSubject.create(); + + TestSubscriber ts = Flowable.fromMaybe(ms) + .test(); + + ts.assertEmpty(); + + assertTrue(ms.hasObservers()); + + ts.cancel(); + + assertFalse(ms.hasObservers()); + } + + @Test + public void asyncFusion() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ASYNC); + + Flowable.fromMaybe(Maybe.just(1)) + .subscribe(ts); + + ts + .assertFuseable() + .assertFusionMode(QueueFuseable.ASYNC) + .assertResult(1); + } + + @Test + public void syncFusionRejected() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.SYNC); + + Flowable.fromMaybe(Maybe.just(1)) + .subscribe(ts); + + ts + .assertFuseable() + .assertFusionMode(QueueFuseable.NONE) + .assertResult(1); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservableTest.java index 5689eadf49..0ef64d192c 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromObservableTest.java @@ -32,4 +32,14 @@ public void error() { .test() .assertFailure(TestException.class); } + + @Test + public void all() { + for (BackpressureStrategy mode : BackpressureStrategy.values()) { + Flowable.fromObservable(Observable.range(1, 5), mode) + .test() + .withTag("mode: " + mode) + .assertResult(1, 2, 3, 4, 5); + } + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnableTest.java new file mode 100644 index 0000000000..f133c8fb99 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromRunnableTest.java @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Supplier; +import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subscribers.TestSubscriber; +import io.reactivex.rxjava3.testsupport.*; + +public class FlowableFromRunnableTest extends RxJavaTest { + @Test + public void fromRunnable() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Flowable.fromRunnable(new Runnable() { + @Override + public void run() { + atomicInteger.incrementAndGet(); + } + }) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromRunnableTwice() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Runnable run = new Runnable() { + @Override + public void run() { + atomicInteger.incrementAndGet(); + } + }; + + Flowable.fromRunnable(run) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + + Flowable.fromRunnable(run) + .test() + .assertResult(); + + assertEquals(2, atomicInteger.get()); + } + + @Test + public void fromRunnableInvokesLazy() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Flowable source = Flowable.fromRunnable(new Runnable() { + @Override + public void run() { + atomicInteger.incrementAndGet(); + } + }); + + assertEquals(0, atomicInteger.get()); + + source + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromRunnableThrows() { + Flowable.fromRunnable(new Runnable() { + @Override + public void run() { + throw new UnsupportedOperationException(); + } + }) + .test() + .assertFailure(UnsupportedOperationException.class); + } + + @SuppressWarnings("unchecked") + @Test + public void callable() throws Throwable { + final int[] counter = { 0 }; + + Flowable m = Flowable.fromRunnable(new Runnable() { + @Override + public void run() { + counter[0]++; + } + }); + + assertTrue(m.getClass().toString(), m instanceof Supplier); + + assertNull(((Supplier)m).get()); + + assertEquals(1, counter[0]); + } + + @Test + public void noErrorLoss() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + final CountDownLatch cdl1 = new CountDownLatch(1); + final CountDownLatch cdl2 = new CountDownLatch(1); + + TestSubscriber ts = Flowable.fromRunnable(new Runnable() { + @Override + public void run() { + cdl1.countDown(); + try { + cdl2.await(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + throw new TestException(e); + } + } + }).subscribeOn(Schedulers.single()).test(); + + assertTrue(cdl1.await(5, TimeUnit.SECONDS)); + + ts.cancel(); + + int timeout = 10; + + while (timeout-- > 0 && errors.isEmpty()) { + Thread.sleep(100); + } + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void disposedUpfront() throws Throwable { + Runnable run = mock(Runnable.class); + + Flowable.fromRunnable(run) + .test(1L, true) + .assertEmpty(); + + verify(run, never()).run(); + } + + @Test + public void cancelWhileRunning() { + final TestSubscriber ts = new TestSubscriber<>(); + + Flowable.fromRunnable(new Runnable() { + @Override + public void run() { + ts.cancel(); + } + }) + .subscribeWith(ts) + .assertEmpty(); + + assertTrue(ts.isCancelled()); + } + + @Test + public void asyncFused() throws Throwable { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ASYNC); + + Runnable action = mock(Runnable.class); + + Flowable.fromRunnable(action) + .subscribe(ts); + + ts.assertFusionMode(QueueFuseable.ASYNC) + .assertResult(); + + verify(action).run(); + } + + @Test + public void syncFusedRejected() throws Throwable { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.SYNC); + + Runnable action = mock(Runnable.class); + + Flowable.fromRunnable(action) + .subscribe(ts); + + ts.assertFusionMode(QueueFuseable.NONE) + .assertResult(); + + verify(action).run(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSingleTest.java new file mode 100644 index 0000000000..01f6b1661f --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFromSingleTest.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.subjects.SingleSubject; +import io.reactivex.rxjava3.subscribers.TestSubscriber; +import io.reactivex.rxjava3.testsupport.TestSubscriberEx; + +public class FlowableFromSingleTest extends RxJavaTest { + + @Test + public void success() { + Flowable.fromSingle(Single.just(1).hide()) + .test() + .assertResult(1); + } + + @Test + public void error() { + Flowable.fromSingle(Single.error(new TestException()).hide()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void cancelComposes() { + SingleSubject ms = SingleSubject.create(); + + TestSubscriber ts = Flowable.fromSingle(ms) + .test(); + + ts.assertEmpty(); + + assertTrue(ms.hasObservers()); + + ts.cancel(); + + assertFalse(ms.hasObservers()); + } + + @Test + public void asyncFusion() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.ASYNC); + + Flowable.fromSingle(Single.just(1)) + .subscribe(ts); + + ts + .assertFuseable() + .assertFusionMode(QueueFuseable.ASYNC) + .assertResult(1); + } + + @Test + public void syncFusionRejected() { + TestSubscriberEx ts = new TestSubscriberEx<>(); + ts.setInitialFusionMode(QueueFuseable.SYNC); + + Flowable.fromSingle(Single.just(1)) + .subscribe(ts); + + ts + .assertFuseable() + .assertFusionMode(QueueFuseable.NONE) + .assertResult(1); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromObservableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromObservableTest.java new file mode 100644 index 0000000000..de2039a4d0 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromObservableTest.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class MaybeFromObservableTest extends RxJavaTest { + + @Test + public void empty() { + Maybe.fromObservable(Observable.empty().hide()) + .test() + .assertResult(); + } + + @Test + public void just() { + Maybe.fromObservable(Observable.just(1).hide()) + .test() + .assertResult(1); + } + + @Test + public void range() { + Maybe.fromObservable(Observable.range(1, 5).hide()) + .test() + .assertResult(1); + } + + @Test + public void error() { + Maybe.fromObservable(Observable.error(new TestException()).hide()) + .test() + .assertFailure(TestException.class); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromPubisherTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromPubisherTest.java new file mode 100644 index 0000000000..bcbef3dc9f --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFromPubisherTest.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class MaybeFromPubisherTest extends RxJavaTest { + + @Test + public void empty() { + Maybe.fromPublisher(Flowable.empty().hide()) + .test() + .assertResult(); + } + + @Test + public void just() { + Maybe.fromPublisher(Flowable.just(1).hide()) + .test() + .assertResult(1); + } + + @Test + public void range() { + Maybe.fromPublisher(Flowable.range(1, 5).hide()) + .test() + .assertResult(1); + } + + @Test + public void error() { + Maybe.fromPublisher(Flowable.error(new TestException()).hide()) + .test() + .assertFailure(TestException.class); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromActionTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromActionTest.java new file mode 100644 index 0000000000..2b6d80896a --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromActionTest.java @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.testsupport.*; + +public class ObservableFromActionTest extends RxJavaTest { + @Test + public void fromAction() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Observable.fromAction(new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + }) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromActionTwice() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Action run = new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + }; + + Observable.fromAction(run) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + + Observable.fromAction(run) + .test() + .assertResult(); + + assertEquals(2, atomicInteger.get()); + } + + @Test + public void fromActionInvokesLazy() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Observable source = Observable.fromAction(new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + }); + + assertEquals(0, atomicInteger.get()); + + source + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromActionThrows() { + Observable.fromAction(new Action() { + @Override + public void run() throws Exception { + throw new UnsupportedOperationException(); + } + }) + .test() + .assertFailure(UnsupportedOperationException.class); + } + + @SuppressWarnings("unchecked") + @Test + public void callable() throws Throwable { + final int[] counter = { 0 }; + + Observable m = Observable.fromAction(new Action() { + @Override + public void run() throws Exception { + counter[0]++; + } + }); + + assertTrue(m.getClass().toString(), m instanceof Supplier); + + assertNull(((Supplier)m).get()); + + assertEquals(1, counter[0]); + } + + @Test + public void noErrorLoss() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + final CountDownLatch cdl1 = new CountDownLatch(1); + final CountDownLatch cdl2 = new CountDownLatch(1); + + TestObserver to = Observable.fromAction(new Action() { + @Override + public void run() throws Exception { + cdl1.countDown(); + cdl2.await(5, TimeUnit.SECONDS); + } + }).subscribeOn(Schedulers.single()).test(); + + assertTrue(cdl1.await(5, TimeUnit.SECONDS)); + + to.dispose(); + + int timeout = 10; + + while (timeout-- > 0 && errors.isEmpty()) { + Thread.sleep(100); + } + + TestHelper.assertUndeliverable(errors, 0, InterruptedException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void disposedUpfront() throws Throwable { + Action run = mock(Action.class); + + Observable.fromAction(run) + .test(true) + .assertEmpty(); + + verify(run, never()).run(); + } + + @Test + public void cancelWhileRunning() { + final TestObserver to = new TestObserver<>(); + + Observable.fromAction(new Action() { + @Override + public void run() throws Exception { + to.dispose(); + } + }) + .subscribeWith(to) + .assertEmpty(); + + assertTrue(to.isDisposed()); + } + + @Test + public void asyncFused() throws Throwable { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.ASYNC); + + Action action = mock(Action.class); + + Observable.fromAction(action) + .subscribe(to); + + to.assertFusionMode(QueueFuseable.ASYNC) + .assertResult(); + + verify(action).run(); + } + + @Test + public void syncFusedRejected() throws Throwable { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.SYNC); + + Action action = mock(Action.class); + + Observable.fromAction(action) + .subscribe(to); + + to.assertFusionMode(QueueFuseable.NONE) + .assertResult(); + + verify(action).run(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletableTest.java new file mode 100644 index 0000000000..6cdc0108d6 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromCompletableTest.java @@ -0,0 +1,195 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.testsupport.*; + +public class ObservableFromCompletableTest extends RxJavaTest { + @Test + public void fromCompletable() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Observable.fromCompletable(Completable.fromAction(new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + })) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromCompletableTwice() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Action run = new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + }; + + Observable.fromCompletable(Completable.fromAction(run)) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + + Observable.fromCompletable(Completable.fromAction(run)) + .test() + .assertResult(); + + assertEquals(2, atomicInteger.get()); + } + + @Test + public void fromCompletableInvokesLazy() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Observable source = Observable.fromCompletable(Completable.fromAction(new Action() { + @Override + public void run() throws Exception { + atomicInteger.incrementAndGet(); + } + })); + + assertEquals(0, atomicInteger.get()); + + source + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromCompletableThrows() { + Observable.fromCompletable(Completable.fromAction(new Action() { + @Override + public void run() throws Exception { + throw new UnsupportedOperationException(); + } + })) + .test() + .assertFailure(UnsupportedOperationException.class); + } + + @Test + public void noErrorLoss() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + final CountDownLatch cdl1 = new CountDownLatch(1); + final CountDownLatch cdl2 = new CountDownLatch(1); + + TestObserver to = Observable.fromCompletable(Completable.fromAction(new Action() { + @Override + public void run() throws Exception { + cdl1.countDown(); + cdl2.await(5, TimeUnit.SECONDS); + } + })).subscribeOn(Schedulers.single()).test(); + + assertTrue(cdl1.await(5, TimeUnit.SECONDS)); + + to.dispose(); + + int timeout = 10; + + while (timeout-- > 0 && errors.isEmpty()) { + Thread.sleep(100); + } + + TestHelper.assertUndeliverable(errors, 0, InterruptedException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void disposedUpfront() throws Throwable { + Action run = mock(Action.class); + + Observable.fromCompletable(Completable.fromAction(run)) + .test(true) + .assertEmpty(); + + verify(run, never()).run(); + } + + @Test + public void cancelWhileRunning() { + final TestObserver to = new TestObserver<>(); + + Observable.fromCompletable(Completable.fromAction(new Action() { + @Override + public void run() throws Exception { + to.dispose(); + } + })) + .subscribeWith(to) + .assertEmpty(); + + assertTrue(to.isDisposed()); + } + + @Test + public void asyncFused() throws Throwable { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.ASYNC); + + Action action = mock(Action.class); + + Observable.fromCompletable(Completable.fromAction(action)) + .subscribe(to); + + to.assertFusionMode(QueueFuseable.ASYNC) + .assertResult(); + + verify(action).run(); + } + + @Test + public void syncFusedRejected() throws Throwable { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.SYNC); + + Action action = mock(Action.class); + + Observable.fromCompletable(Completable.fromAction(action)) + .subscribe(to); + + to.assertFusionMode(QueueFuseable.NONE) + .assertResult(); + + verify(action).run(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromMaybeTest.java new file mode 100644 index 0000000000..185b363d57 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromMaybeTest.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.subjects.MaybeSubject; +import io.reactivex.rxjava3.testsupport.TestObserverEx; + +public class ObservableFromMaybeTest extends RxJavaTest { + + @Test + public void success() { + Observable.fromMaybe(Maybe.just(1).hide()) + .test() + .assertResult(1); + } + + @Test + public void empty() { + Observable.fromMaybe(Maybe.empty().hide()) + .test() + .assertResult(); + } + + @Test + public void error() { + Observable.fromMaybe(Maybe.error(new TestException()).hide()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void cancelComposes() { + MaybeSubject ms = MaybeSubject.create(); + + TestObserver to = Observable.fromMaybe(ms) + .test(); + + to.assertEmpty(); + + assertTrue(ms.hasObservers()); + + to.dispose(); + + assertFalse(ms.hasObservers()); + } + + @Test + public void asyncFusion() { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.ASYNC); + + Observable.fromMaybe(Maybe.just(1)) + .subscribe(to); + + to + .assertFuseable() + .assertFusionMode(QueueFuseable.ASYNC) + .assertResult(1); + } + + @Test + public void syncFusionRejected() { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.SYNC); + + Observable.fromMaybe(Maybe.just(1)) + .subscribe(to); + + to + .assertFuseable() + .assertFusionMode(QueueFuseable.NONE) + .assertResult(1); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnableTest.java new file mode 100644 index 0000000000..834abbd978 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromRunnableTest.java @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Supplier; +import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.testsupport.*; + +public class ObservableFromRunnableTest extends RxJavaTest { + @Test + public void fromRunnable() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Observable.fromRunnable(new Runnable() { + @Override + public void run() { + atomicInteger.incrementAndGet(); + } + }) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromRunnableTwice() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Runnable run = new Runnable() { + @Override + public void run() { + atomicInteger.incrementAndGet(); + } + }; + + Observable.fromRunnable(run) + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + + Observable.fromRunnable(run) + .test() + .assertResult(); + + assertEquals(2, atomicInteger.get()); + } + + @Test + public void fromRunnableInvokesLazy() { + final AtomicInteger atomicInteger = new AtomicInteger(); + + Observable source = Observable.fromRunnable(new Runnable() { + @Override + public void run() { + atomicInteger.incrementAndGet(); + } + }); + + assertEquals(0, atomicInteger.get()); + + source + .test() + .assertResult(); + + assertEquals(1, atomicInteger.get()); + } + + @Test + public void fromRunnableThrows() { + Observable.fromRunnable(new Runnable() { + @Override + public void run() { + throw new UnsupportedOperationException(); + } + }) + .test() + .assertFailure(UnsupportedOperationException.class); + } + + @SuppressWarnings("unchecked") + @Test + public void callable() throws Throwable { + final int[] counter = { 0 }; + + Observable m = Observable.fromRunnable(new Runnable() { + @Override + public void run() { + counter[0]++; + } + }); + + assertTrue(m.getClass().toString(), m instanceof Supplier); + + assertNull(((Supplier)m).get()); + + assertEquals(1, counter[0]); + } + + @Test + public void noErrorLoss() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + final CountDownLatch cdl1 = new CountDownLatch(1); + final CountDownLatch cdl2 = new CountDownLatch(1); + + TestObserver to = Observable.fromRunnable(new Runnable() { + @Override + public void run() { + cdl1.countDown(); + try { + cdl2.await(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + throw new TestException(e); + } + } + }).subscribeOn(Schedulers.single()).test(); + + assertTrue(cdl1.await(5, TimeUnit.SECONDS)); + + to.dispose(); + + int timeout = 10; + + while (timeout-- > 0 && errors.isEmpty()) { + Thread.sleep(100); + } + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void disposedUpfront() throws Throwable { + Runnable run = mock(Runnable.class); + + Observable.fromRunnable(run) + .test(true) + .assertEmpty(); + + verify(run, never()).run(); + } + + @Test + public void cancelWhileRunning() { + final TestObserver to = new TestObserver<>(); + + Observable.fromRunnable(new Runnable() { + @Override + public void run() { + to.dispose(); + } + }) + .subscribeWith(to) + .assertEmpty(); + + assertTrue(to.isDisposed()); + } + + @Test + public void asyncFused() throws Throwable { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.ASYNC); + + Runnable action = mock(Runnable.class); + + Observable.fromRunnable(action) + .subscribe(to); + + to.assertFusionMode(QueueFuseable.ASYNC) + .assertResult(); + + verify(action).run(); + } + + @Test + public void syncFusedRejected() throws Throwable { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.SYNC); + + Runnable action = mock(Runnable.class); + + Observable.fromRunnable(action) + .subscribe(to); + + to.assertFusionMode(QueueFuseable.NONE) + .assertResult(); + + verify(action).run(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSingleTest.java new file mode 100644 index 0000000000..d77498cea8 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableFromSingleTest.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.internal.fuseable.QueueFuseable; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.subjects.SingleSubject; +import io.reactivex.rxjava3.testsupport.TestObserverEx; + +public class ObservableFromSingleTest extends RxJavaTest { + + @Test + public void success() { + Observable.fromSingle(Single.just(1).hide()) + .test() + .assertResult(1); + } + + @Test + public void error() { + Observable.fromSingle(Single.error(new TestException()).hide()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void cancelComposes() { + SingleSubject ms = SingleSubject.create(); + + TestObserver to = Observable.fromSingle(ms) + .test(); + + to.assertEmpty(); + + assertTrue(ms.hasObservers()); + + to.dispose(); + + assertFalse(ms.hasObservers()); + } + + @Test + public void asyncFusion() { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.ASYNC); + + Observable.fromSingle(Single.just(1)) + .subscribe(to); + + to + .assertFuseable() + .assertFusionMode(QueueFuseable.ASYNC) + .assertResult(1); + } + + @Test + public void syncFusionRejected() { + TestObserverEx to = new TestObserverEx<>(); + to.setInitialFusionMode(QueueFuseable.SYNC); + + Observable.fromSingle(Single.just(1)) + .subscribe(to); + + to + .assertFuseable() + .assertFusionMode(QueueFuseable.NONE) + .assertResult(1); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromMaybeTest.java new file mode 100644 index 0000000000..50eed426a7 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFromMaybeTest.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import static org.junit.Assert.*; + +import java.util.NoSuchElementException; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.subjects.MaybeSubject; + +public class SingleFromMaybeTest extends RxJavaTest { + + @Test + public void success() { + Single.fromMaybe(Maybe.just(1).hide()) + .test() + .assertResult(1); + } + + @Test + public void empty() { + Single.fromMaybe(Maybe.empty().hide()) + .test() + .assertFailure(NoSuchElementException.class); + } + + @Test + public void emptyDefault() { + Single.fromMaybe(Maybe.empty().hide(), 1) + .test() + .assertResult(1); + } + + @Test + public void error() { + Single.fromMaybe(Maybe.error(new TestException()).hide()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void cancelComposes() { + MaybeSubject ms = MaybeSubject.create(); + + TestObserver to = Single.fromMaybe(ms) + .test(); + + to.assertEmpty(); + + assertTrue(ms.hasObservers()); + + to.dispose(); + + assertFalse(ms.hasObservers()); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java index d99202adef..60b5a11fb6 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java @@ -83,6 +83,7 @@ public static void main(String[] args) throws IOException { Map notesMap = new HashMap<>(); List notesList = new ArrayList<>(); List tbdList = new ArrayList<>(); + int[] counters = new int[CLASSES.length]; for (String operatorName : sortedOperators) { out.print("`"); out.print(operatorName); out.print("`|"); + int m = 0; for (Class clazz : CLASSES) { if (operatorMap.get(clazz).contains(operatorName)) { out.print(PRESENT); + counters[m]++; } else { String notes = findNotes(clazz.getSimpleName(), operatorName); if (notes != null) { @@ -116,9 +119,19 @@ public static void main(String[] args) throws IOException { } } out.print("|"); + m++; } out.println(); } + out.print("**"); + out.print(sortedOperators.size()); + out.print(" operators** |"); + for (int m = 0; m < counters.length; m++) { + out.print(" **"); + out.print(counters[m]); + out.print("** |"); + } + out.println(); if (!notesList.isEmpty()) { out.println(); @@ -316,6 +329,7 @@ static String findNotes(String clazzName, String operatorName) { " C flattenStreamAsObservable Always empty thus no items to map.", " MSC forEach Use [`subscribe()`](#subscribe).", " MSC forEachWhile Use [`subscribe()`](#subscribe).", + " S fromAction Never empty.", " M fromArray At most one item. Use [`just()`](#just) or [`empty()`](#empty).", " S fromArray Always one item. Use [`just()`](#just).", " C fromArray Always empty. Use [`complete()`](#complete).", @@ -328,6 +342,7 @@ static String findNotes(String clazzName, String operatorName) { " O fromObservable Use [`wrap()`](#wrap).", " S fromOptional Always one item. Use [`just()`](#just).", " C fromOptional Always empty. Use [`complete()`](#complete).", + " S fromRunnable Never empty.", " S fromSingle Use [`wrap()`](#wrap).", " M fromStream At most one item. Use [`just()`](#just) or [`empty()`](#empty).", " S fromStream Always one item. Use [`just()`](#just).", diff --git a/src/test/java/io/reactivex/rxjava3/validators/InternalWrongNaming.java b/src/test/java/io/reactivex/rxjava3/validators/InternalWrongNaming.java index 14d937502f..a1ad772f05 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/InternalWrongNaming.java +++ b/src/test/java/io/reactivex/rxjava3/validators/InternalWrongNaming.java @@ -62,7 +62,7 @@ static void checkInternalOperatorNaming(String baseClassName, String consumerCla fail.append("java.lang.RuntimeException: " + g.getName() + " mentions " + consumerClassName) .append("\r\n at io.reactivex.internal.operators.") .append(baseClassName.toLowerCase()).append(".").append(g.getName().replace(".java", "")) - .append(" (").append(g.getName()).append(":").append(i + 1).append(")\r\n\r\n"); + .append(".method(").append(g.getName()).append(":").append(i + 1).append(")\r\n\r\n"); count++; } @@ -170,6 +170,9 @@ public void flowableNoObserver() throws Exception { "FlowableCountSingle", "FlowableElementAtMaybe", "FlowableElementAtSingle", + "FlowableElementAtMaybePublisher", + "FlowableElementAtSinglePublisher", + "FlowableFromCompletable", "FlowableSingleSingle", "FlowableSingleMaybe", "FlowableLastMaybe", From d5449b2fd63c73dea06fbbd5d584bab7b9cfde5d Mon Sep 17 00:00:00 2001 From: David Karnok Date: Sun, 26 Jan 2020 10:25:53 +0100 Subject: [PATCH 20/37] 3.x: Add timeInterval & timestamp to M/S (#6874) * 3.x: Add timeInterval & timestamp to M/S * Fix null not allowed in Timed * Fix Timed coverage --- docs/Operator-Matrix.md | 46 ++-- .../java/io/reactivex/rxjava3/core/Maybe.java | 228 +++++++++++++++++- .../io/reactivex/rxjava3/core/Single.java | 228 +++++++++++++++++- .../operators/maybe/MaybeTimeInterval.java | 105 ++++++++ .../operators/single/SingleTimeInterval.java | 100 ++++++++ .../reactivex/rxjava3/schedulers/Timed.java | 6 +- .../maybe/MaybeTimeIntervalTest.java | 111 +++++++++ .../operators/maybe/MaybeTimestampTest.java | 111 +++++++++ .../single/SingleTimeIntervalTest.java | 103 ++++++++ .../operators/single/SingleTimestampTest.java | 103 ++++++++ .../util/OperatorMatrixGenerator.java | 1 + .../rxjava3/schedulers/TimedTest.java | 2 +- .../rxjava3/validators/JavadocWording.java | 4 +- 13 files changed, 1114 insertions(+), 34 deletions(-) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeInterval.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeInterval.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeIntervalTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimestampTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeIntervalTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimestampTest.java diff --git a/docs/Operator-Matrix.md b/docs/Operator-Matrix.md index 81e1f7878d..10427533cc 100644 --- a/docs/Operator-Matrix.md +++ b/docs/Operator-Matrix.md @@ -58,7 +58,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `defer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `delay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `delaySubscription`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`dematerialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`dematerialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `distinct`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `distinctUntilChanged`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `doAfterNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| @@ -212,10 +212,10 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `throttleLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `throttleLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `throttleWithTimeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`timeInterval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`timeInterval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `timeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `timer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `to`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toCompletionStage`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -237,7 +237,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([108](#notes-108))| `zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([109](#notes-109))| `zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([110](#notes-110))| -**237 operators** | **215** | **209** | **108** | **93** | **76** | +**237 operators** | **215** | **209** | **111** | **95** | **76** | #### Notes 1 Use [`contains()`](#contains).
@@ -372,25 +372,19 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat 17. Single.concatMapMaybe() 18. Maybe.concatMapSingle() 19. Single.concatMapSingle() -20. Maybe.dematerialize() -21. Maybe.doOnLifecycle() -22. Single.doOnLifecycle() -23. Completable.doOnLifecycle() -24. Single.mergeArray() -25. Single.mergeArrayDelayError() -26. Single.ofType() -27. Completable.onErrorReturn() -28. Completable.onErrorReturnItem() -29. Maybe.safeSubscribe() -30. Single.safeSubscribe() -31. Completable.safeSubscribe() -32. Completable.sequenceEqual() -33. Maybe.startWith() -34. Single.startWith() -35. Maybe.timeInterval() -36. Single.timeInterval() -37. Completable.timeInterval() -38. Maybe.timestamp() -39. Single.timestamp() -40. Maybe.toFuture() -41. Completable.toFuture() +20. Maybe.doOnLifecycle() +21. Single.doOnLifecycle() +22. Completable.doOnLifecycle() +23. Single.mergeArray() +24. Single.mergeArrayDelayError() +25. Single.ofType() +26. Completable.onErrorReturn() +27. Completable.onErrorReturnItem() +28. Maybe.safeSubscribe() +29. Single.safeSubscribe() +30. Completable.safeSubscribe() +31. Completable.sequenceEqual() +32. Maybe.startWith() +33. Single.startWith() +34. Maybe.toFuture() +35. Completable.toFuture() diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 12ab3678e2..03e73abe65 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -34,7 +34,7 @@ import io.reactivex.rxjava3.internal.util.ErrorMode; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.schedulers.*; /** * The {@code Maybe} class represents a deferred computation and emission of a single value, no value at all or an exception. @@ -4991,6 +4991,232 @@ public final Maybe takeUntil(@NonNull Publisher other) { return RxJavaPlugins.onAssembly(new MaybeTakeUntilPublisher<>(this, other)); } + /** + * Measures the time (in milliseconds) between the subscription and success item emission + * of the current {@code Maybe} and signals it as a tuple ({@link Timed}) + * success value. + *

+ * + *

+ * If the current {@code Maybe} is empty or fails, the resulting {@code Maybe} will + * pass along the signals to the downstream. To measure the time to termination, + * use {@link #materialize()} and apply {@link Single#timeInterval()}. + *

+ *
Scheduler:
+ *
{@code timeInterval} uses the {@code computation} {@link Scheduler} + * for determining the current time upon subscription and upon receiving the + * success item from the current {@code Maybe}.
+ *
+ * @return the new {@code Maybe} instance + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.COMPUTATION) + public final Maybe> timeInterval() { + return timeInterval(TimeUnit.MILLISECONDS, Schedulers.computation()); + } + + /** + * Measures the time (in milliseconds) between the subscription and success item emission + * of the current {@code Maybe} and signals it as a tuple ({@link Timed}) + * success value. + *

+ * + *

+ * If the current {@code Maybe} is empty or fails, the resulting {@code Maybe} will + * pass along the signals to the downstream. To measure the time to termination, + * use {@link #materialize()} and apply {@link Single#timeInterval(Scheduler)}. + *

+ *
Scheduler:
+ *
{@code timeInterval} uses the provided {@link Scheduler} + * for determining the current time upon subscription and upon receiving the + * success item from the current {@code Maybe}.
+ *
+ * @param scheduler the {@code Scheduler} used for providing the current time + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code scheduler} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.CUSTOM) + public final Maybe> timeInterval(@NonNull Scheduler scheduler) { + return timeInterval(TimeUnit.MILLISECONDS, scheduler); + } + + /** + * Measures the time between the subscription and success item emission + * of the current {@code Maybe} and signals it as a tuple ({@link Timed}) + * success value. + *

+ * + *

+ * If the current {@code Maybe} is empty or fails, the resulting {@code Maybe} will + * pass along the signals to the downstream. To measure the time to termination, + * use {@link #materialize()} and apply {@link Single#timeInterval(TimeUnit)}. + *

+ *
Scheduler:
+ *
{@code timeInterval} uses the {@code computation} {@link Scheduler} + * for determining the current time upon subscription and upon receiving the + * success item from the current {@code Maybe}.
+ *
+ * @param unit the time unit for measurement + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code unit} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.COMPUTATION) + public final Maybe> timeInterval(@NonNull TimeUnit unit) { + return timeInterval(unit, Schedulers.computation()); + } + + /** + * Measures the time between the subscription and success item emission + * of the current {@code Maybe} and signals it as a tuple ({@link Timed}) + * success value. + *

+ * + *

+ * If the current {@code Maybe} is empty or fails, the resulting {@code Maybe} will + * pass along the signals to the downstream. To measure the time to termination, + * use {@link #materialize()} and apply {@link Single#timeInterval(TimeUnit, Scheduler)}. + *

+ *
Scheduler:
+ *
{@code timeInterval} uses the provided {@link Scheduler} + * for determining the current time upon subscription and upon receiving the + * success item from the current {@code Maybe}.
+ *
+ * @param unit the time unit for measurement + * @param scheduler the {@code Scheduler} used for providing the current time + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.CUSTOM) + public final Maybe> timeInterval(@NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + return RxJavaPlugins.onAssembly(new MaybeTimeInterval<>(this, unit, scheduler, true)); + } + + /** + * Combines the success value from the current {@code Maybe} with the current time (in milliseconds) of + * its reception, using the {@code computation} {@link Scheduler} as time source, + * then signals them as a {@link Timed} instance. + *

+ * + *

+ * If the current {@code Maybe} is empty or fails, the resulting {@code Maybe} will + * pass along the signals to the downstream. To measure the time to termination, + * use {@link #materialize()} and apply {@link Single#timestamp()}. + *

+ *
Scheduler:
+ *
{@code timestamp} uses the {@code computation} {@code Scheduler} + * for determining the current time upon receiving the + * success item from the current {@code Maybe}.
+ *
+ * @return the new {@code Maybe} instance + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.COMPUTATION) + public final Maybe> timestamp() { + return timestamp(TimeUnit.MILLISECONDS, Schedulers.computation()); + } + + /** + * Combines the success value from the current {@code Maybe} with the current time (in milliseconds) of + * its reception, using the given {@link Scheduler} as time source, + * then signals them as a {@link Timed} instance. + *

+ * + *

+ * If the current {@code Maybe} is empty or fails, the resulting {@code Maybe} will + * pass along the signals to the downstream. To measure the time to termination, + * use {@link #materialize()} and apply {@link Single#timestamp(Scheduler)}. + *

+ *
Scheduler:
+ *
{@code timestamp} uses the provided {@code Scheduler} + * for determining the current time upon receiving the + * success item from the current {@code Maybe}.
+ *
+ * @param scheduler the {@code Scheduler} used for providing the current time + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code scheduler} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.CUSTOM) + public final Maybe> timestamp(@NonNull Scheduler scheduler) { + return timestamp(TimeUnit.MILLISECONDS, scheduler); + } + + /** + * Combines the success value from the current {@code Maybe} with the current time of + * its reception, using the {@code computation} {@link Scheduler} as time source, + * then signals it as a {@link Timed} instance. + *

+ * + *

+ * If the current {@code Maybe} is empty or fails, the resulting {@code Maybe} will + * pass along the signals to the downstream. To measure the time to termination, + * use {@link #materialize()} and apply {@link Single#timestamp(TimeUnit)}. + *

+ *
Scheduler:
+ *
{@code timestamp} uses the {@code computation} {@code Scheduler}, + * for determining the current time upon receiving the + * success item from the current {@code Maybe}.
+ *
+ * @param unit the time unit for measurement + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code unit} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.COMPUTATION) + public final Maybe> timestamp(@NonNull TimeUnit unit) { + return timestamp(unit, Schedulers.computation()); + } + + /** + * Combines the success value from the current {@code Maybe} with the current time of + * its reception, using the given {@link Scheduler} as time source, + * then signals it as a {@link Timed} instance. + *

+ * + *

+ * If the current {@code Maybe} is empty or fails, the resulting {@code Maybe} will + * pass along the signals to the downstream. To measure the time to termination, + * use {@link #materialize()} and apply {@link Single#timestamp(TimeUnit, Scheduler)}. + *

+ *
Scheduler:
+ *
{@code timestamp} uses the provided {@code Scheduler}, + * which is used for determining the current time upon receiving the + * success item from the current {@code Maybe}.
+ *
+ * @param unit the time unit for measurement + * @param scheduler the {@code Scheduler} used for providing the current time + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.CUSTOM) + public final Maybe> timestamp(@NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + return RxJavaPlugins.onAssembly(new MaybeTimeInterval<>(this, unit, scheduler, false)); + } + /** * Returns a {@code Maybe} that mirrors the current {@code Maybe} but applies a timeout policy for each emitted * item. If the next item isn't emitted within the specified timeout duration starting from its predecessor, diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index a3b536b1f7..697c1355b5 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -36,7 +36,7 @@ import io.reactivex.rxjava3.internal.util.ErrorMode; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; -import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.schedulers.*; /** * The {@code Single} class implements the Reactive Pattern for a single value response. @@ -4137,6 +4137,232 @@ public final Single subscribeOn(@NonNull Scheduler scheduler) { return RxJavaPlugins.onAssembly(new SingleSubscribeOn<>(this, scheduler)); } + /** + * Measures the time (in milliseconds) between the subscription and success item emission + * of the current {@code Single} and signals it as a tuple ({@link Timed}) + * success value. + *

+ * + *

+ * If the current {@code Single} fails, the resulting {@code Single} will + * pass along the signal to the downstream. To measure the time to error, + * use {@link #materialize()} and apply {@link #timeInterval()}. + *

+ *
Scheduler:
+ *
{@code timeInterval} uses the {@code computation} {@link Scheduler} + * for determining the current time upon subscription and upon receiving the + * success item from the current {@code Single}.
+ *
+ * @return the new {@code Single} instance + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.COMPUTATION) + public final Single> timeInterval() { + return timeInterval(TimeUnit.MILLISECONDS, Schedulers.computation()); + } + + /** + * Measures the time (in milliseconds) between the subscription and success item emission + * of the current {@code Single} and signals it as a tuple ({@link Timed}) + * success value. + *

+ * + *

+ * If the current {@code Single} fails, the resulting {@code Single} will + * pass along the signal to the downstream. To measure the time to error, + * use {@link #materialize()} and apply {@link #timeInterval(Scheduler)}. + *

+ *
Scheduler:
+ *
{@code timeInterval} uses the provided {@link Scheduler} + * for determining the current time upon subscription and upon receiving the + * success item from the current {@code Single}.
+ *
+ * @param scheduler the {@code Scheduler} used for providing the current time + * @return the new {@code Single} instance + * @throws NullPointerException if {@code scheduler} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.CUSTOM) + public final Single> timeInterval(@NonNull Scheduler scheduler) { + return timeInterval(TimeUnit.MILLISECONDS, scheduler); + } + + /** + * Measures the time between the subscription and success item emission + * of the current {@code Single} and signals it as a tuple ({@link Timed}) + * success value. + *

+ * + *

+ * If the current {@code Single} fails, the resulting {@code Single} will + * pass along the signals to the downstream. To measure the time to error, + * use {@link #materialize()} and apply {@link #timeInterval(TimeUnit, Scheduler)}. + *

+ *
Scheduler:
+ *
{@code timeInterval} uses the {@code computation} {@link Scheduler} + * for determining the current time upon subscription and upon receiving the + * success item from the current {@code Single}.
+ *
+ * @param unit the time unit for measurement + * @return the new {@code Single} instance + * @throws NullPointerException if {@code unit} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.COMPUTATION) + public final Single> timeInterval(@NonNull TimeUnit unit) { + return timeInterval(unit, Schedulers.computation()); + } + + /** + * Measures the time between the subscription and success item emission + * of the current {@code Single} and signals it as a tuple ({@link Timed}) + * success value. + *

+ * + *

+ * If the current {@code Single} is empty or fails, the resulting {@code Single} will + * pass along the signals to the downstream. To measure the time to termination, + * use {@link #materialize()} and apply {@link #timeInterval(TimeUnit, Scheduler)}. + *

+ *
Scheduler:
+ *
{@code timeInterval} uses the provided {@link Scheduler} + * for determining the current time upon subscription and upon receiving the + * success item from the current {@code Single}.
+ *
+ * @param unit the time unit for measurement + * @param scheduler the {@code Scheduler} used for providing the current time + * @return the new {@code Single} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.CUSTOM) + public final Single> timeInterval(@NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + return RxJavaPlugins.onAssembly(new SingleTimeInterval<>(this, unit, scheduler, true)); + } + + /** + * Combines the success value from the current {@code Single} with the current time (in milliseconds) of + * its reception, using the {@code computation} {@link Scheduler} as time source, + * then signals them as a {@link Timed} instance. + *

+ * + *

+ * If the current {@code Single} is empty or fails, the resulting {@code Single} will + * pass along the signals to the downstream. To get the timestamp of the error, + * use {@link #materialize()} and apply {@link #timestamp()}. + *

+ *
Scheduler:
+ *
{@code timestamp} uses the {@code computation} {@code Scheduler} + * for determining the current time upon receiving the + * success item from the current {@code Single}.
+ *
+ * @return the new {@code Single} instance + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.COMPUTATION) + public final Single> timestamp() { + return timestamp(TimeUnit.MILLISECONDS, Schedulers.computation()); + } + + /** + * Combines the success value from the current {@code Single} with the current time (in milliseconds) of + * its reception, using the given {@link Scheduler} as time source, + * then signals them as a {@link Timed} instance. + *

+ * + *

+ * If the current {@code Single} is empty or fails, the resulting {@code Single} will + * pass along the signals to the downstream. To get the timestamp of the error, + * use {@link #materialize()} and apply {@link #timestamp(Scheduler)}. + *

+ *
Scheduler:
+ *
{@code timestamp} uses the provided {@code Scheduler} + * for determining the current time upon receiving the + * success item from the current {@code Single}.
+ *
+ * @param scheduler the {@code Scheduler} used for providing the current time + * @return the new {@code Single} instance + * @throws NullPointerException if {@code scheduler} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.CUSTOM) + public final Single> timestamp(@NonNull Scheduler scheduler) { + return timestamp(TimeUnit.MILLISECONDS, scheduler); + } + + /** + * Combines the success value from the current {@code Single} with the current time of + * its reception, using the {@code computation} {@link Scheduler} as time source, + * then signals it as a {@link Timed} instance. + *

+ * + *

+ * If the current {@code Single} is empty or fails, the resulting {@code Single} will + * pass along the signals to the downstream. To get the timestamp of the error, + * use {@link #materialize()} and apply {@link #timestamp(TimeUnit)}. + *

+ *
Scheduler:
+ *
{@code timestamp} uses the {@code computation} {@code Scheduler}, + * for determining the current time upon receiving the + * success item from the current {@code Single}.
+ *
+ * @param unit the time unit for measurement + * @return the new {@code Single} instance + * @throws NullPointerException if {@code unit} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.COMPUTATION) + public final Single> timestamp(@NonNull TimeUnit unit) { + return timestamp(unit, Schedulers.computation()); + } + + /** + * Combines the success value from the current {@code Single} with the current time of + * its reception, using the given {@link Scheduler} as time source, + * then signals it as a {@link Timed} instance. + *

+ * + *

+ * If the current {@code Single} is empty or fails, the resulting {@code Single} will + * pass along the signals to the downstream. To get the timestamp of the error, + * use {@link #materialize()} and apply {@link #timestamp(TimeUnit, Scheduler)}. + *

+ *
Scheduler:
+ *
{@code timestamp} uses the provided {@code Scheduler}, + * which is used for determining the current time upon receiving the + * success item from the current {@code Single}.
+ *
+ * @param unit the time unit for measurement + * @param scheduler the {@code Scheduler} used for providing the current time + * @return the new {@code Single} instance + * @throws NullPointerException if {@code unit} or {@code scheduler} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.CUSTOM) + public final Single> timestamp(@NonNull TimeUnit unit, @NonNull Scheduler scheduler) { + Objects.requireNonNull(unit, "unit is null"); + Objects.requireNonNull(scheduler, "scheduler is null"); + return RxJavaPlugins.onAssembly(new SingleTimeInterval<>(this, unit, scheduler, false)); + } + /** * Returns a {@code Single} that emits the item emitted by the current {@code Single} until a {@link CompletableSource} terminates. Upon * termination of {@code other}, this will emit a {@link CancellationException} rather than go to diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeInterval.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeInterval.java new file mode 100644 index 0000000000..af30ee3a1d --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeInterval.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; +import io.reactivex.rxjava3.schedulers.Timed; + +/** + * Measures the time between subscription and the success item emission + * from the upstream and emits this as a {@link Timed} success value. + * @param the element type of the sequence + * @since 3.0.0 + */ +public final class MaybeTimeInterval extends Maybe> { + + final MaybeSource source; + + final TimeUnit unit; + + final Scheduler scheduler; + + final boolean start; + + public MaybeTimeInterval(MaybeSource source, TimeUnit unit, Scheduler scheduler, boolean start) { + this.source = source; + this.unit = unit; + this.scheduler = scheduler; + this.start = start; + } + + @Override + protected void subscribeActual(@NonNull MaybeObserver> observer) { + source.subscribe(new TimeIntervalMaybeObserver<>(observer, unit, scheduler, start)); + } + + static final class TimeIntervalMaybeObserver implements MaybeObserver, Disposable { + + final MaybeObserver> downstream; + + final TimeUnit unit; + + final Scheduler scheduler; + + final long startTime; + + Disposable upstream; + + TimeIntervalMaybeObserver(MaybeObserver> downstream, TimeUnit unit, Scheduler scheduler, boolean start) { + this.downstream = downstream; + this.unit = unit; + this.scheduler = scheduler; + this.startTime = start ? scheduler.now(unit) : 0L; + } + + @Override + public void onSubscribe(@NonNull Disposable d) { + if (DisposableHelper.validate(this.upstream, d)) { + this.upstream = d; + + downstream.onSubscribe(this); + } + } + + @Override + public void onSuccess(@NonNull T t) { + downstream.onSuccess(new Timed<>(t, scheduler.now(unit) - startTime, unit)); + } + + @Override + public void onError(@NonNull Throwable e) { + downstream.onError(e); + } + + @Override + public void onComplete() { + downstream.onComplete(); + } + + @Override + public void dispose() { + upstream.dispose(); + } + + @Override + public boolean isDisposed() { + return upstream.isDisposed(); + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeInterval.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeInterval.java new file mode 100644 index 0000000000..2eac3bbc3a --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeInterval.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; +import io.reactivex.rxjava3.schedulers.Timed; + +/** + * Measures the time between subscription and the success item emission + * from the upstream and emits this as a {@link Timed} success value. + * @param the element type of the sequence + * @since 3.0.0 + */ +public final class SingleTimeInterval extends Single> { + + final SingleSource source; + + final TimeUnit unit; + + final Scheduler scheduler; + + final boolean start; + + public SingleTimeInterval(SingleSource source, TimeUnit unit, Scheduler scheduler, boolean start) { + this.source = source; + this.unit = unit; + this.scheduler = scheduler; + this.start = start; + } + + @Override + protected void subscribeActual(@NonNull SingleObserver> observer) { + source.subscribe(new TimeIntervalSingleObserver<>(observer, unit, scheduler, start)); + } + + static final class TimeIntervalSingleObserver implements SingleObserver, Disposable { + + final SingleObserver> downstream; + + final TimeUnit unit; + + final Scheduler scheduler; + + final long startTime; + + Disposable upstream; + + TimeIntervalSingleObserver(SingleObserver> downstream, TimeUnit unit, Scheduler scheduler, boolean start) { + this.downstream = downstream; + this.unit = unit; + this.scheduler = scheduler; + this.startTime = start ? scheduler.now(unit) : 0L; + } + + @Override + public void onSubscribe(@NonNull Disposable d) { + if (DisposableHelper.validate(this.upstream, d)) { + this.upstream = d; + + downstream.onSubscribe(this); + } + } + + @Override + public void onSuccess(@NonNull T t) { + downstream.onSuccess(new Timed<>(t, scheduler.now(unit) - startTime, unit)); + } + + @Override + public void onError(@NonNull Throwable e) { + downstream.onError(e); + } + + @Override + public void dispose() { + upstream.dispose(); + } + + @Override + public boolean isDisposed() { + return upstream.isDisposed(); + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/schedulers/Timed.java b/src/main/java/io/reactivex/rxjava3/schedulers/Timed.java index 814b223dcf..a7b6cc46e7 100644 --- a/src/main/java/io/reactivex/rxjava3/schedulers/Timed.java +++ b/src/main/java/io/reactivex/rxjava3/schedulers/Timed.java @@ -33,10 +33,10 @@ public final class Timed { * @param value the value to hold * @param time the time to hold * @param unit the time unit, not null - * @throws NullPointerException if unit is {@code null} + * @throws NullPointerException if {@code value} or {@code unit} is {@code null} */ public Timed(@NonNull T value, long time, @NonNull TimeUnit unit) { - this.value = value; + this.value = Objects.requireNonNull(value, "value is null"); this.time = time; this.unit = Objects.requireNonNull(unit, "unit is null"); } @@ -89,7 +89,7 @@ public boolean equals(Object other) { @Override public int hashCode() { - int h = value != null ? value.hashCode() : 0; + int h = value.hashCode(); h = h * 31 + (int)((time >>> 31) ^ time); h = h * 31 + unit.hashCode(); return h; diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeIntervalTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeIntervalTest.java new file mode 100644 index 0000000000..30b770aed4 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimeIntervalTest.java @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Maybe; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.schedulers.*; +import io.reactivex.rxjava3.subjects.MaybeSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class MaybeTimeIntervalTest { + + @Test + public void just() { + Maybe.just(1) + .timeInterval() + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void empty() { + Maybe.empty() + .timeInterval() + .test() + .assertResult(); + } + + @Test + public void error() { + Maybe.error(new TestException()) + .timeInterval() + .test() + .assertFailure(TestException.class); + } + + @Test + public void justSeconds() { + Maybe.just(1) + .timeInterval(TimeUnit.SECONDS) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void justScheduler() { + Maybe.just(1) + .timeInterval(Schedulers.single()) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void justSecondsScheduler() { + Maybe.just(1) + .timeInterval(TimeUnit.SECONDS, Schedulers.single()) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeMaybe(m -> m.timeInterval()); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(MaybeSubject.create().timeInterval()); + } + + @Test + public void timeInfo() { + TestScheduler scheduler = new TestScheduler(); + + MaybeSubject ms = MaybeSubject.create(); + + TestObserver> to = ms + .timeInterval(scheduler) + .test(); + + scheduler.advanceTimeBy(1000, TimeUnit.MILLISECONDS); + + ms.onSuccess(1); + + to.assertResult(new Timed<>(1, 1000L, TimeUnit.MILLISECONDS)); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimestampTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimestampTest.java new file mode 100644 index 0000000000..1ce230f8d0 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeTimestampTest.java @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Maybe; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.schedulers.*; +import io.reactivex.rxjava3.subjects.MaybeSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class MaybeTimestampTest { + + @Test + public void just() { + Maybe.just(1) + .timestamp() + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void empty() { + Maybe.empty() + .timestamp() + .test() + .assertResult(); + } + + @Test + public void error() { + Maybe.error(new TestException()) + .timestamp() + .test() + .assertFailure(TestException.class); + } + + @Test + public void justSeconds() { + Maybe.just(1) + .timestamp(TimeUnit.SECONDS) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void justScheduler() { + Maybe.just(1) + .timestamp(Schedulers.single()) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void justSecondsScheduler() { + Maybe.just(1) + .timestamp(TimeUnit.SECONDS, Schedulers.single()) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeMaybe(m -> m.timestamp()); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(MaybeSubject.create().timestamp()); + } + + @Test + public void timeInfo() { + TestScheduler scheduler = new TestScheduler(); + + MaybeSubject ms = MaybeSubject.create(); + + TestObserver> to = ms + .timestamp(scheduler) + .test(); + + scheduler.advanceTimeBy(1000, TimeUnit.MILLISECONDS); + + ms.onSuccess(1); + + to.assertResult(new Timed<>(1, 1000L, TimeUnit.MILLISECONDS)); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeIntervalTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeIntervalTest.java new file mode 100644 index 0000000000..09dd26eeba --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimeIntervalTest.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.schedulers.*; +import io.reactivex.rxjava3.subjects.SingleSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleTimeIntervalTest { + + @Test + public void just() { + Single.just(1) + .timestamp() + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void error() { + Single.error(new TestException()) + .timestamp() + .test() + .assertFailure(TestException.class); + } + + @Test + public void justSeconds() { + Single.just(1) + .timestamp(TimeUnit.SECONDS) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void justScheduler() { + Single.just(1) + .timestamp(Schedulers.single()) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void justSecondsScheduler() { + Single.just(1) + .timestamp(TimeUnit.SECONDS, Schedulers.single()) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeSingle(m -> m.timestamp()); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(SingleSubject.create().timestamp()); + } + + @Test + public void timeInfo() { + TestScheduler scheduler = new TestScheduler(); + + SingleSubject ss = SingleSubject.create(); + + TestObserver> to = ss + .timestamp(scheduler) + .test(); + + scheduler.advanceTimeBy(1000, TimeUnit.MILLISECONDS); + + ss.onSuccess(1); + + to.assertResult(new Timed<>(1, 1000L, TimeUnit.MILLISECONDS)); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimestampTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimestampTest.java new file mode 100644 index 0000000000..a282c0345e --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleTimestampTest.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.schedulers.*; +import io.reactivex.rxjava3.subjects.SingleSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleTimestampTest { + + @Test + public void just() { + Single.just(1) + .timeInterval() + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void error() { + Single.error(new TestException()) + .timeInterval() + .test() + .assertFailure(TestException.class); + } + + @Test + public void justSeconds() { + Single.just(1) + .timeInterval(TimeUnit.SECONDS) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void justScheduler() { + Single.just(1) + .timeInterval(Schedulers.single()) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void justSecondsScheduler() { + Single.just(1) + .timeInterval(TimeUnit.SECONDS, Schedulers.single()) + .test() + .assertValueCount(1) + .assertNoErrors() + .assertComplete(); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeSingle(m -> m.timeInterval()); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(SingleSubject.create().timeInterval()); + } + + @Test + public void timeInfo() { + TestScheduler scheduler = new TestScheduler(); + + SingleSubject ss = SingleSubject.create(); + + TestObserver> to = ss + .timeInterval(scheduler) + .test(); + + scheduler.advanceTimeBy(1000, TimeUnit.MILLISECONDS); + + ss.onSuccess(1); + + to.assertResult(new Timed<>(1, 1000L, TimeUnit.MILLISECONDS)); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java index 60b5a11fb6..a0ba3e52e4 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java @@ -458,6 +458,7 @@ static String findNotes(String clazzName, String operatorName) { " C throttleLatest Always empty thus no items to work with.", " MS throttleWithTimeout At most one item signaled so no subsequent items to work with.", " C throttleWithTimeout Always empty thus no items to work with.", + " C timeInterval Always empty thus no items to work with.", " C timestamp Always empty thus no items to work with.", "FO toCompletionStage Use [`firstStage`](#firstStage), [`lastStage`](#lastStage) or [`singleStage`](#singleStage).", "F toFlowable Would be no-op.", diff --git a/src/test/java/io/reactivex/rxjava3/schedulers/TimedTest.java b/src/test/java/io/reactivex/rxjava3/schedulers/TimedTest.java index d7a5eb752e..ce117c2fb7 100644 --- a/src/test/java/io/reactivex/rxjava3/schedulers/TimedTest.java +++ b/src/test/java/io/reactivex/rxjava3/schedulers/TimedTest.java @@ -39,7 +39,7 @@ public void hashCodeOf() { assertEquals(TimeUnit.SECONDS.hashCode() + 31 * (5 + 31 * 1), t1.hashCode()); - Timed t2 = new Timed<>(null, 5, TimeUnit.SECONDS); + Timed t2 = new Timed<>(0, 5, TimeUnit.SECONDS); assertEquals(TimeUnit.SECONDS.hashCode() + 31 * (5 + 31 * 0), t2.hashCode()); } diff --git a/src/test/java/io/reactivex/rxjava3/validators/JavadocWording.java b/src/test/java/io/reactivex/rxjava3/validators/JavadocWording.java index d351e7809d..e22fdd9521 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/JavadocWording.java +++ b/src/test/java/io/reactivex/rxjava3/validators/JavadocWording.java @@ -153,12 +153,12 @@ public void maybeDocRefersToMaybeTypes() throws Exception { jdx = 0; for (;;) { int idx = m.javadoc.indexOf("Single", jdx); - if (idx >= 0) { + if (idx >= 0 && m.javadoc.indexOf("Single#", jdx) != idx) { int j = m.javadoc.indexOf("#toSingle", jdx); int k = m.javadoc.indexOf("{@code Single", jdx); if (!m.signature.contains("Single") && (j + 3 != idx && k + 7 != idx)) { e.append("java.lang.RuntimeException: Maybe doc mentions Single but not in the signature\r\n at io.reactivex.rxjava3.core.") - .append("Maybe(Maybe.java:").append(m.javadocLine + lineNumber(m.javadoc, idx) - 1).append(")\r\n\r\n"); + .append("Maybe.method(Maybe.java:").append(m.javadocLine + lineNumber(m.javadoc, idx) - 1).append(")\r\n\r\n"); } jdx = idx + 6; } else { From 8c85f5a52115b419beeb84b0e2dc9bb4aa6bcd0f Mon Sep 17 00:00:00 2001 From: David Karnok Date: Sun, 26 Jan 2020 12:36:52 +0100 Subject: [PATCH 21/37] 3.x: Add Maybe/Completable toFuture (#6875) * 3.x: Add Maybe/Completable toFuture * Fix copy-paste mistakes --- .../reactivex/rxjava3/core/Completable.java | 22 +++++ .../io/reactivex/rxjava3/core/Flowable.java | 2 +- .../java/io/reactivex/rxjava3/core/Maybe.java | 23 +++++ .../io/reactivex/rxjava3/core/Observable.java | 2 +- .../io/reactivex/rxjava3/core/Single.java | 4 +- ...Observer.java => FutureMultiObserver.java} | 18 +++- .../completable/CompletableToFutureTest.java | 76 +++++++++++++++++ .../operators/maybe/MaybeToFutureTest.java | 84 +++++++++++++++++++ 8 files changed, 224 insertions(+), 7 deletions(-) rename src/main/java/io/reactivex/rxjava3/internal/observers/{FutureSingleObserver.java => FutureMultiObserver.java} (89%) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFutureTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFutureTest.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index e965855e00..1c6214e1da 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -2892,6 +2892,28 @@ public final Flowable toFlowable() { } return RxJavaPlugins.onAssembly(new CompletableToFlowable<>(this)); } + /** + * Returns a {@link Future} representing the termination of the current {@code Completable} + * via a {@code null} value. + *

+ * + *

+ * Cancelling the {@code Future} will cancel the subscription to the current {@code Completable}. + *

+ *
Scheduler:
+ *
{@code toFuture} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @return the new {@code Future} instance + * @see ReactiveX documentation: To + * @since 3.0.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Future toFuture() { + return subscribeWith(new FutureMultiObserver<>()); + } /** * Converts this {@code Completable} into a {@link Maybe}. diff --git a/src/main/java/io/reactivex/rxjava3/core/Flowable.java b/src/main/java/io/reactivex/rxjava3/core/Flowable.java index 3d83d477c5..a994e526c5 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Flowable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Flowable.java @@ -6249,7 +6249,7 @@ public final T blockingSingle(@NonNull T defaultItem) { /** * Returns a {@link Future} representing the only value emitted by this {@code Flowable}. *

- * + * *

* If the {@code Flowable} emits more than one item, {@link java.util.concurrent.Future} will receive an * {@link java.lang.IndexOutOfBoundsException}. If the {@code Flowable} is empty, {@link java.util.concurrent.Future} diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 03e73abe65..8b1b569aeb 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -4166,6 +4166,29 @@ public final Flowable toFlowable() { return RxJavaPlugins.onAssembly(new MaybeToFlowable<>(this)); } + /** + * Returns a {@link Future} representing the single value emitted by the current {@code Maybe} + * or {@code null} if the current {@code Maybe} is empty. + *

+ * + *

+ * Cancelling the {@code Future} will cancel the subscription to the current {@code Maybe}. + *

+ *
Scheduler:
+ *
{@code toFuture} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @return the new {@code Future} instance + * @see ReactiveX documentation: To + * @since 3.0.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Future toFuture() { + return subscribeWith(new FutureMultiObserver<>()); + } + /** * Converts this {@code Maybe} into an {@link Observable} instance composing disposal * through. diff --git a/src/main/java/io/reactivex/rxjava3/core/Observable.java b/src/main/java/io/reactivex/rxjava3/core/Observable.java index 89de9dd63e..3ab0be1ab9 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Observable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Observable.java @@ -5654,7 +5654,7 @@ public final T blockingSingle(@NonNull T defaultItem) { /** * Returns a {@link Future} representing the only value emitted by the current {@code Observable}. *

- * + * *

* If the {@code Observable} emits more than one item, {@code Future} will receive an * {@link IndexOutOfBoundsException}. If the {@code Observable} is empty, {@code Future} diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 697c1355b5..a283d9eef0 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -4625,6 +4625,8 @@ public final Flowable toFlowable() { * Returns a {@link Future} representing the single value emitted by this {@code Single}. *

* + *

+ * Cancelling the {@code Future} will cancel the subscription to the current {@code Single}. *

*
Scheduler:
*
{@code toFuture} does not operate by default on a particular {@link Scheduler}.
@@ -4637,7 +4639,7 @@ public final Flowable toFlowable() { @SchedulerSupport(SchedulerSupport.NONE) @NonNull public final Future toFuture() { - return subscribeWith(new FutureSingleObserver<>()); + return subscribeWith(new FutureMultiObserver<>()); } /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/FutureSingleObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/FutureMultiObserver.java similarity index 89% rename from src/main/java/io/reactivex/rxjava3/internal/observers/FutureSingleObserver.java rename to src/main/java/io/reactivex/rxjava3/internal/observers/FutureMultiObserver.java index 3e55963bea..e2f2aeea5a 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/observers/FutureSingleObserver.java +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/FutureMultiObserver.java @@ -19,7 +19,7 @@ import java.util.concurrent.atomic.AtomicReference; import io.reactivex.rxjava3.annotations.NonNull; -import io.reactivex.rxjava3.core.SingleObserver; +import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.internal.disposables.DisposableHelper; import io.reactivex.rxjava3.internal.util.BlockingHelper; @@ -31,15 +31,15 @@ * * @param the value type */ -public final class FutureSingleObserver extends CountDownLatch -implements SingleObserver, Future, Disposable { +public final class FutureMultiObserver extends CountDownLatch +implements MaybeObserver, SingleObserver, CompletableObserver, Future, Disposable { T value; Throwable error; final AtomicReference upstream; - public FutureSingleObserver() { + public FutureMultiObserver() { super(1); this.upstream = new AtomicReference<>(); } @@ -141,6 +141,16 @@ public void onError(Throwable t) { } } + @Override + public void onComplete() { + Disposable a = upstream.get(); + if (a == DisposableHelper.DISPOSED) { + return; + } + upstream.compareAndSet(a, this); + countDown(); + } + @Override public void dispose() { // ignoring as `this` means a finished Disposable only diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFutureTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFutureTest.java new file mode 100644 index 0000000000..7501a2fe85 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableToFutureTest.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.completable; + +import static org.junit.Assert.*; + +import java.util.concurrent.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subjects.CompletableSubject; + +public class CompletableToFutureTest extends RxJavaTest { + + @Test + public void empty() throws Exception { + assertNull(Completable.complete() + .subscribeOn(Schedulers.computation()) + .toFuture() + .get()); + } + + @Test + public void error() throws InterruptedException { + try { + Completable.error(new TestException()) + .subscribeOn(Schedulers.computation()) + .toFuture() + .get(); + + fail("Should have thrown!"); + } catch (ExecutionException ex) { + assertTrue("" + ex.getCause(), ex.getCause() instanceof TestException); + } + } + + @Test + public void cancel() { + CompletableSubject cs = CompletableSubject.create(); + + Future f = cs.toFuture(); + + assertTrue(cs.hasObservers()); + + f.cancel(true); + + assertFalse(cs.hasObservers()); + } + + @Test + public void cancel2() { + CompletableSubject cs = CompletableSubject.create(); + + Future f = cs.toFuture(); + + assertTrue(cs.hasObservers()); + + f.cancel(false); + + assertFalse(cs.hasObservers()); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFutureTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFutureTest.java new file mode 100644 index 0000000000..37723dc656 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeToFutureTest.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import static org.junit.Assert.*; + +import java.util.concurrent.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subjects.MaybeSubject; + +public class MaybeToFutureTest extends RxJavaTest { + + @Test + public void success() throws Exception { + assertEquals((Integer)1, Maybe.just(1) + .subscribeOn(Schedulers.computation()) + .toFuture() + .get()); + } + + @Test + public void empty() throws Exception { + assertNull(Maybe.empty() + .subscribeOn(Schedulers.computation()) + .toFuture() + .get()); + } + + @Test + public void error() throws InterruptedException { + try { + Maybe.error(new TestException()) + .subscribeOn(Schedulers.computation()) + .toFuture() + .get(); + + fail("Should have thrown!"); + } catch (ExecutionException ex) { + assertTrue("" + ex.getCause(), ex.getCause() instanceof TestException); + } + } + + @Test + public void cancel() { + MaybeSubject ms = MaybeSubject.create(); + + Future f = ms.toFuture(); + + assertTrue(ms.hasObservers()); + + f.cancel(true); + + assertFalse(ms.hasObservers()); + } + + @Test + public void cancel2() { + MaybeSubject ms = MaybeSubject.create(); + + Future f = ms.toFuture(); + + assertTrue(ms.hasObservers()); + + f.cancel(false); + + assertFalse(ms.hasObservers()); + } +} From db0bd715bb512976fb0cac20a89af8176b1e1b22 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Sun, 26 Jan 2020 15:44:47 +0100 Subject: [PATCH 22/37] 3.x: Add Single.ofType (#6876) --- .../java/io/reactivex/rxjava3/core/Maybe.java | 6 +- .../io/reactivex/rxjava3/core/Single.java | 24 +++++ .../operators/single/SingleOfTypeTest.java | 96 +++++++++++++++++++ .../rxjava3/testsupport/TestHelper.java | 24 +++++ 4 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOfTypeTest.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 8b1b569aeb..b2a6465eae 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -3472,7 +3472,7 @@ public final Maybe doOnSuccess(@NonNull Consumer onSuccess) { * Filters the success item of the {@code Maybe} via a predicate function and emitting it if the predicate * returns {@code true}, completing otherwise. *

- * + * *

*
Scheduler:
*
{@code filter} does not operate by default on a particular {@link Scheduler}.
@@ -4098,10 +4098,10 @@ public final Maybe observeOn(@NonNull Scheduler scheduler) { } /** - * Filters the items emitted by a {@code Maybe}, only emitting its success value if that + * Filters the items emitted by the current {@code Maybe}, only emitting its success value if that * is an instance of the supplied {@link Class}. *

- * + * *

*
Scheduler:
*
{@code ofType} does not operate by default on a particular {@link Scheduler}.
diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index a283d9eef0..12400b1fd0 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -3439,6 +3439,30 @@ public final Single contains(@NonNull Object item, @NonNull BiPredicate public final Flowable mergeWith(@NonNull SingleSource other) { return merge(this, other); } + /** + * Filters the items emitted by the current {@code Single}, only emitting its success value if that + * is an instance of the supplied {@link Class}. + *

+ * + *

+ *
Scheduler:
+ *
{@code ofType} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the output type + * @param clazz + * the class type to filter the items emitted by the current {@code Single} + * @return the new {@link Maybe} instance + * @throws NullPointerException if {@code clazz} is {@code null} + * @see ReactiveX operators documentation: Filter + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Maybe ofType(@NonNull Class clazz) { + Objects.requireNonNull(clazz, "clazz is null"); + return filter(Functions.isInstanceOf(clazz)).cast(clazz); + } /** * Signals the success item or the terminal signals of the current {@code Single} on the specified {@link Scheduler}, diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOfTypeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOfTypeTest.java new file mode 100644 index 0000000000..3ce3a0d15e --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleOfTypeTest.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.processors.PublishProcessor; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleOfTypeTest extends RxJavaTest { + + @Test + public void normal() { + Single.just(1).ofType(Integer.class) + .test() + .assertResult(1); + } + + @Test + public void normalDowncast() { + TestObserver to = Single.just(1) + .ofType(Number.class) + .test(); + // don't make this fluent, target type required! + to.assertResult((Number)1); + } + + @Test + public void notInstance() { + TestObserver to = Single.just(1) + .ofType(String.class) + .test(); + // don't make this fluent, target type required! + to.assertResult(); + } + + @Test + public void error() { + TestObserver to = Single.error(new TestException()) + .ofType(Number.class) + .test(); + // don't make this fluent, target type required! + to.assertFailure(TestException.class); + } + + @Test + public void errorNotInstance() { + TestObserver to = Single.error(new TestException()) + .ofType(String.class) + .test(); + // don't make this fluent, target type required! + to.assertFailure(TestException.class); + } + + @Test + public void dispose() { + TestHelper.checkDisposedSingleToMaybe(new Function, Maybe>() { + @Override + public Maybe apply(Single m) throws Exception { + return m.ofType(Object.class); + } + }); + } + + @Test + public void isDisposed() { + PublishProcessor pp = PublishProcessor.create(); + + TestHelper.checkDisposed(pp.singleElement().ofType(Object.class)); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeSingleToMaybe(new Function, Maybe>() { + @Override + public Maybe apply(Single f) throws Exception { + return f.ofType(Object.class); + } + }); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/testsupport/TestHelper.java b/src/test/java/io/reactivex/rxjava3/testsupport/TestHelper.java index f50354b6a5..bb6608e96d 100644 --- a/src/test/java/io/reactivex/rxjava3/testsupport/TestHelper.java +++ b/src/test/java/io/reactivex/rxjava3/testsupport/TestHelper.java @@ -2248,6 +2248,30 @@ public static void checkDisposedMaybeToSingle(Function, ? extend assertFalse(pp.hasSubscribers()); } + /** + * Check if the operator applied to a Maybe source propagates dispose properly. + * @param the source value type + * @param the output value type + * @param composer the function to apply an operator to the provided Maybe source + */ + public static void checkDisposedSingleToMaybe(Function, ? extends MaybeSource> composer) { + PublishProcessor pp = PublishProcessor.create(); + + TestSubscriber ts = new TestSubscriber<>(); + + try { + new MaybeToFlowable<>(composer.apply(pp.singleOrError())).subscribe(ts); + } catch (Throwable ex) { + throw ExceptionHelper.wrapOrThrow(ex); + } + + assertTrue(pp.hasSubscribers()); + + ts.cancel(); + + assertFalse(pp.hasSubscribers()); + } + /** * Check if the TestSubscriber has a CompositeException with the specified class * of Throwables in the given order. From 4257ef563a3bf017e0703c00057daf12b54738ba Mon Sep 17 00:00:00 2001 From: David Karnok Date: Sun, 26 Jan 2020 17:50:26 +0100 Subject: [PATCH 23/37] 3.x: Add doOnLifecycle to M/S/C (#6877) --- docs/Operator-Matrix.md | 34 ++-- .../reactivex/rxjava3/core/Completable.java | 29 +++ .../java/io/reactivex/rxjava3/core/Maybe.java | 28 +++ .../io/reactivex/rxjava3/core/Single.java | 29 +++ .../operators/maybe/MaybeDoOnLifecycle.java | 125 +++++++++++++ .../operators/single/SingleDoOnLifecycle.java | 119 +++++++++++++ .../CompletableDoOnLifecycleTest.java | 153 ++++++++++++++++ .../maybe/MaybeDoOnLifecycleTest.java | 168 ++++++++++++++++++ .../single/SingleDoOnLifecycleTest.java | 152 ++++++++++++++++ 9 files changed, 817 insertions(+), 20 deletions(-) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycle.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycle.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnLifecycleTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycleTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycleTest.java diff --git a/docs/Operator-Matrix.md b/docs/Operator-Matrix.md index 10427533cc..a44eed94ec 100644 --- a/docs/Operator-Matrix.md +++ b/docs/Operator-Matrix.md @@ -71,7 +71,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `doOnEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `doOnError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `doOnEvent`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnLifecycle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`doOnLifecycle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `doOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| `doOnRequest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| `doOnSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -144,7 +144,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `mergeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `never`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `observeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`ofType`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))| +`ofType`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))| `onBackpressureBuffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| `onBackpressureDrop`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| `onBackpressureLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| @@ -219,7 +219,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `to`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toCompletionStage`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`toFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| `toMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| `toMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -237,7 +237,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([108](#notes-108))| `zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([109](#notes-109))| `zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([110](#notes-110))| -**237 operators** | **215** | **209** | **111** | **95** | **76** | +**237 operators** | **215** | **209** | **113** | **97** | **78** | #### Notes 1 Use [`contains()`](#contains).
@@ -372,19 +372,13 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat 17. Single.concatMapMaybe() 18. Maybe.concatMapSingle() 19. Single.concatMapSingle() -20. Maybe.doOnLifecycle() -21. Single.doOnLifecycle() -22. Completable.doOnLifecycle() -23. Single.mergeArray() -24. Single.mergeArrayDelayError() -25. Single.ofType() -26. Completable.onErrorReturn() -27. Completable.onErrorReturnItem() -28. Maybe.safeSubscribe() -29. Single.safeSubscribe() -30. Completable.safeSubscribe() -31. Completable.sequenceEqual() -32. Maybe.startWith() -33. Single.startWith() -34. Maybe.toFuture() -35. Completable.toFuture() +20. Single.mergeArray() +21. Single.mergeArrayDelayError() +22. Completable.onErrorReturn() +23. Completable.onErrorReturnItem() +24. Maybe.safeSubscribe() +25. Single.safeSubscribe() +26. Completable.safeSubscribe() +27. Completable.sequenceEqual() +28. Maybe.startWith() +29. Single.startWith() diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 1c6214e1da..9febbd1204 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -18,6 +18,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; +import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; @@ -1751,6 +1752,34 @@ public final Completable doOnEvent(@NonNull Consumer<@Nullable ? super Throwable return RxJavaPlugins.onAssembly(new CompletableDoOnEvent(this, onEvent)); } + /** + * Calls the appropriate {@code onXXX} method (shared between all {@link CompletableObserver}s) for the lifecycle events of + * the sequence (subscription, disposal). + *

+ * + *

+ *
Scheduler:
+ *
{@code doOnLifecycle} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param onSubscribe + * a {@link Consumer} called with the {@link Disposable} sent via {@link CompletableObserver#onSubscribe(Disposable)} + * @param onDispose + * called when the downstream disposes the {@code Disposable} via {@code dispose()} + * @return the new {@code Completable} instance + * @throws NullPointerException if {@code onSubscribe} or {@code onDispose} is {@code null} + * @see ReactiveX operators documentation: Do + * @since 3.0.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Completable doOnLifecycle(@NonNull Consumer onSubscribe, @NonNull Action onDispose) { + return doOnLifecycle(onSubscribe, Functions.emptyConsumer(), + Functions.EMPTY_ACTION, Functions.EMPTY_ACTION, + Functions.EMPTY_ACTION, onDispose); + } + /** * Returns a {@code Completable} instance that calls the various callbacks upon the specific * lifecycle events. diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index b2a6465eae..b3ed8213d4 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -3388,6 +3388,34 @@ public final Maybe doOnEvent(@NonNull BiConsumer<@Nullable ? super T, @Nullab return RxJavaPlugins.onAssembly(new MaybeDoOnEvent<>(this, onEvent)); } + /** + * Calls the appropriate {@code onXXX} method (shared between all {@link MaybeObserver}s) for the lifecycle events of + * the sequence (subscription, disposal). + *

+ * + *

+ *
Scheduler:
+ *
{@code doOnLifecycle} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param onSubscribe + * a {@link Consumer} called with the {@link Disposable} sent via {@link MaybeObserver#onSubscribe(Disposable)} + * @param onDispose + * called when the downstream disposes the {@code Disposable} via {@code dispose()} + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code onSubscribe} or {@code onDispose} is {@code null} + * @see ReactiveX operators documentation: Do + * @since 3.0.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Maybe doOnLifecycle(@NonNull Consumer onSubscribe, @NonNull Action onDispose) { + Objects.requireNonNull(onSubscribe, "onSubscribe is null"); + Objects.requireNonNull(onDispose, "onDispose is null"); + return RxJavaPlugins.onAssembly(new MaybeDoOnLifecycle<>(this, onSubscribe, onDispose)); + } + /** * Calls the shared {@link Consumer} with the {@link Disposable} sent through the {@code onSubscribe} for each * {@link MaybeObserver} that subscribes to the current {@code Maybe}. diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 12400b1fd0..81b0aaaffe 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -2684,6 +2684,34 @@ public final Single doFinally(@NonNull Action onFinally) { return RxJavaPlugins.onAssembly(new SingleDoFinally<>(this, onFinally)); } + /** + * Calls the appropriate {@code onXXX} method (shared between all {@link SingleObserver}s) for the lifecycle events of + * the sequence (subscription, disposal). + *

+ * + *

+ *
Scheduler:
+ *
{@code doOnLifecycle} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param onSubscribe + * a {@link Consumer} called with the {@link Disposable} sent via {@link SingleObserver#onSubscribe(Disposable)} + * @param onDispose + * called when the downstream disposes the {@code Disposable} via {@code dispose()} + * @return the new {@code Single} instance + * @throws NullPointerException if {@code onSubscribe} or {@code onDispose} is {@code null} + * @see ReactiveX operators documentation: Do + * @since 3.0.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public final Single doOnLifecycle(@NonNull Consumer onSubscribe, @NonNull Action onDispose) { + Objects.requireNonNull(onSubscribe, "onSubscribe is null"); + Objects.requireNonNull(onDispose, "onDispose is null"); + return RxJavaPlugins.onAssembly(new SingleDoOnLifecycle<>(this, onSubscribe, onDispose)); + } + /** * Calls the shared consumer with the {@link Disposable} sent through the {@code onSubscribe} for each * {@link SingleObserver} that subscribes to the current {@code Single}. @@ -3455,6 +3483,7 @@ public final Flowable mergeWith(@NonNull SingleSource other) { * @return the new {@link Maybe} instance * @throws NullPointerException if {@code clazz} is {@code null} * @see ReactiveX operators documentation: Filter + * @since 3.0.0 */ @CheckReturnValue @NonNull diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycle.java new file mode 100644 index 0000000000..3355c79014 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycle.java @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ +package io.reactivex.rxjava3.internal.operators.maybe; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.disposables.*; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Invokes callbacks upon {@code onSubscribe} from upstream and + * {@code dispose} from downstream. + * + * @param the element type of the flow + * @since 3.0.0 + */ +public final class MaybeDoOnLifecycle extends AbstractMaybeWithUpstream { + + final Consumer onSubscribe; + + final Action onDispose; + + public MaybeDoOnLifecycle(Maybe upstream, Consumer onSubscribe, + Action onDispose) { + super(upstream); + this.onSubscribe = onSubscribe; + this.onDispose = onDispose; + } + + @Override + protected void subscribeActual(MaybeObserver observer) { + source.subscribe(new MaybeLifecycleObserver<>(observer, onSubscribe, onDispose)); + } + + static final class MaybeLifecycleObserver implements MaybeObserver, Disposable { + + final MaybeObserver downstream; + + final Consumer onSubscribe; + + final Action onDispose; + + Disposable upstream; + + MaybeLifecycleObserver(MaybeObserver downstream, Consumer onSubscribe, Action onDispose) { + this.downstream = downstream; + this.onSubscribe = onSubscribe; + this.onDispose = onDispose; + } + + @Override + public void onSubscribe(@NonNull Disposable d) { + // this way, multiple calls to onSubscribe can show up in tests that use doOnSubscribe to validate behavior + try { + onSubscribe.accept(d); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + d.dispose(); + this.upstream = DisposableHelper.DISPOSED; + EmptyDisposable.error(e, downstream); + return; + } + if (DisposableHelper.validate(this.upstream, d)) { + this.upstream = d; + downstream.onSubscribe(this); + } + } + + @Override + public void onSuccess(@NonNull T t) { + if (upstream != DisposableHelper.DISPOSED) { + upstream = DisposableHelper.DISPOSED; + downstream.onSuccess(t); + } + } + + @Override + public void onError(@NonNull Throwable e) { + if (upstream != DisposableHelper.DISPOSED) { + upstream = DisposableHelper.DISPOSED; + downstream.onError(e); + } else { + RxJavaPlugins.onError(e); + } + } + + @Override + public void onComplete() { + if (upstream != DisposableHelper.DISPOSED) { + upstream = DisposableHelper.DISPOSED; + downstream.onComplete(); + } + } + + @Override + public void dispose() { + try { + onDispose.run(); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + RxJavaPlugins.onError(e); + } + upstream.dispose(); + upstream = DisposableHelper.DISPOSED; + } + + @Override + public boolean isDisposed() { + return upstream.isDisposed(); + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycle.java new file mode 100644 index 0000000000..288e8970cd --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycle.java @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ +package io.reactivex.rxjava3.internal.operators.single; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.disposables.*; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Invokes callbacks upon {@code onSubscribe} from upstream and + * {@code dispose} from downstream. + * + * @param the element type of the flow + * @since 3.0.0 + */ +public final class SingleDoOnLifecycle extends Single { + + final Single source; + + final Consumer onSubscribe; + + final Action onDispose; + + public SingleDoOnLifecycle(Single upstream, Consumer onSubscribe, + Action onDispose) { + this.source = upstream; + this.onSubscribe = onSubscribe; + this.onDispose = onDispose; + } + + @Override + protected void subscribeActual(SingleObserver observer) { + source.subscribe(new SingleLifecycleObserver<>(observer, onSubscribe, onDispose)); + } + + static final class SingleLifecycleObserver implements SingleObserver, Disposable { + + final SingleObserver downstream; + + final Consumer onSubscribe; + + final Action onDispose; + + Disposable upstream; + + SingleLifecycleObserver(SingleObserver downstream, Consumer onSubscribe, Action onDispose) { + this.downstream = downstream; + this.onSubscribe = onSubscribe; + this.onDispose = onDispose; + } + + @Override + public void onSubscribe(@NonNull Disposable d) { + // this way, multiple calls to onSubscribe can show up in tests that use doOnSubscribe to validate behavior + try { + onSubscribe.accept(d); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + d.dispose(); + this.upstream = DisposableHelper.DISPOSED; + EmptyDisposable.error(e, downstream); + return; + } + if (DisposableHelper.validate(this.upstream, d)) { + this.upstream = d; + downstream.onSubscribe(this); + } + } + + @Override + public void onSuccess(@NonNull T t) { + if (upstream != DisposableHelper.DISPOSED) { + upstream = DisposableHelper.DISPOSED; + downstream.onSuccess(t); + } + } + + @Override + public void onError(@NonNull Throwable e) { + if (upstream != DisposableHelper.DISPOSED) { + upstream = DisposableHelper.DISPOSED; + downstream.onError(e); + } else { + RxJavaPlugins.onError(e); + } + } + + @Override + public void dispose() { + try { + onDispose.run(); + } catch (Throwable e) { + Exceptions.throwIfFatal(e); + RxJavaPlugins.onError(e); + } + upstream.dispose(); + upstream = DisposableHelper.DISPOSED; + } + + @Override + public boolean isDisposed() { + return upstream.isDisposed(); + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnLifecycleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnLifecycleTest.java new file mode 100644 index 0000000000..3e85e1e027 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableDoOnLifecycleTest.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.completable; + +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.subjects.CompletableSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class CompletableDoOnLifecycleTest extends RxJavaTest { + + @Test + public void empty() throws Throwable { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + Completable.complete() + .doOnLifecycle(onSubscribe, onDispose) + .test() + .assertResult(); + + verify(onSubscribe).accept(any()); + verify(onDispose, never()).run(); + } + + @Test + public void error() throws Throwable { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + Completable.error(new TestException()) + .doOnLifecycle(onSubscribe, onDispose) + .test() + .assertFailure(TestException.class); + + verify(onSubscribe).accept(any()); + verify(onDispose, never()).run(); + } + + @Test + public void onSubscribeCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + doThrow(new TestException("First")).when(onSubscribe).accept(any()); + + Disposable bs = Disposable.empty(); + + new Completable() { + @Override + protected void subscribeActual(CompletableObserver observer) { + observer.onSubscribe(bs); + observer.onError(new TestException("Second")); + observer.onComplete(); + } + } + .doOnLifecycle(onSubscribe, onDispose) + .to(TestHelper.testConsumer()) + .assertFailureAndMessage(TestException.class, "First"); + + assertTrue(bs.isDisposed()); + + TestHelper.assertUndeliverable(errors, 0, TestException.class, "Second"); + + verify(onSubscribe).accept(any()); + verify(onDispose, never()).run(); + }); + } + + @Test + public void onDisposeCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + doThrow(new TestException("First")).when(onDispose).run(); + + CompletableSubject cs = CompletableSubject.create(); + + TestObserver to = cs + .doOnLifecycle(onSubscribe, onDispose) + .test(); + + assertTrue(cs.hasObservers()); + + to.dispose(); + + assertFalse(cs.hasObservers()); + + TestHelper.assertUndeliverable(errors, 0, TestException.class, "First"); + + verify(onSubscribe).accept(any()); + verify(onDispose).run(); + }); + } + + @Test + public void dispose() throws Throwable { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + CompletableSubject cs = CompletableSubject.create(); + + TestObserver to = cs + .doOnLifecycle(onSubscribe, onDispose) + .test(); + + assertTrue(cs.hasObservers()); + + to.dispose(); + + assertFalse(cs.hasObservers()); + + verify(onSubscribe).accept(any()); + verify(onDispose).run(); + } + + @Test + public void isDisposed() { + TestHelper.checkDisposed(CompletableSubject.create().doOnLifecycle(d -> { }, () -> { })); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeCompletable(m -> m.doOnLifecycle(d -> { }, () -> { })); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycleTest.java new file mode 100644 index 0000000000..b8921b7eb9 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeDoOnLifecycleTest.java @@ -0,0 +1,168 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.subjects.MaybeSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class MaybeDoOnLifecycleTest extends RxJavaTest { + + @Test + public void success() throws Throwable { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + Maybe.just(1) + .doOnLifecycle(onSubscribe, onDispose) + .test() + .assertResult(1); + + verify(onSubscribe).accept(any()); + verify(onDispose, never()).run(); + } + + @Test + public void empty() throws Throwable { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + Maybe.empty() + .doOnLifecycle(onSubscribe, onDispose) + .test() + .assertResult(); + + verify(onSubscribe).accept(any()); + verify(onDispose, never()).run(); + } + + @Test + public void error() throws Throwable { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + Maybe.error(new TestException()) + .doOnLifecycle(onSubscribe, onDispose) + .test() + .assertFailure(TestException.class); + + verify(onSubscribe).accept(any()); + verify(onDispose, never()).run(); + } + + @Test + public void onSubscribeCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + doThrow(new TestException("First")).when(onSubscribe).accept(any()); + + Disposable bs = Disposable.empty(); + + new Maybe() { + @Override + protected void subscribeActual(MaybeObserver observer) { + observer.onSubscribe(bs); + observer.onError(new TestException("Second")); + observer.onComplete(); + observer.onSuccess(1); + } + } + .doOnLifecycle(onSubscribe, onDispose) + .to(TestHelper.testConsumer()) + .assertFailureAndMessage(TestException.class, "First"); + + assertTrue(bs.isDisposed()); + + TestHelper.assertUndeliverable(errors, 0, TestException.class, "Second"); + + verify(onSubscribe).accept(any()); + verify(onDispose, never()).run(); + }); + } + + @Test + public void onDisposeCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + doThrow(new TestException("First")).when(onDispose).run(); + + MaybeSubject ms = MaybeSubject.create(); + + TestObserver to = ms + .doOnLifecycle(onSubscribe, onDispose) + .test(); + + assertTrue(ms.hasObservers()); + + to.dispose(); + + assertFalse(ms.hasObservers()); + + TestHelper.assertUndeliverable(errors, 0, TestException.class, "First"); + + verify(onSubscribe).accept(any()); + verify(onDispose).run(); + }); + } + + @Test + public void dispose() throws Throwable { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + MaybeSubject ms = MaybeSubject.create(); + + TestObserver to = ms + .doOnLifecycle(onSubscribe, onDispose) + .test(); + + assertTrue(ms.hasObservers()); + + to.dispose(); + + assertFalse(ms.hasObservers()); + + verify(onSubscribe).accept(any()); + verify(onDispose).run(); + } + + @Test + public void isDisposed() { + TestHelper.checkDisposed(MaybeSubject.create().doOnLifecycle(d -> { }, () -> { })); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeMaybe(m -> m.doOnLifecycle(d -> { }, () -> { })); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycleTest.java new file mode 100644 index 0000000000..9208ab2be8 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleDoOnLifecycleTest.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.subjects.SingleSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleDoOnLifecycleTest extends RxJavaTest { + + @Test + public void success() throws Throwable { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + Single.just(1) + .doOnLifecycle(onSubscribe, onDispose) + .test() + .assertResult(1); + + verify(onSubscribe).accept(any()); + verify(onDispose, never()).run(); + } + + @Test + public void error() throws Throwable { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + Single.error(new TestException()) + .doOnLifecycle(onSubscribe, onDispose) + .test() + .assertFailure(TestException.class); + + verify(onSubscribe).accept(any()); + verify(onDispose, never()).run(); + } + + @Test + public void onSubscribeCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + doThrow(new TestException("First")).when(onSubscribe).accept(any()); + + Disposable bs = Disposable.empty(); + + new Single() { + @Override + protected void subscribeActual(SingleObserver observer) { + observer.onSubscribe(bs); + observer.onError(new TestException("Second")); + observer.onSuccess(1); + } + } + .doOnLifecycle(onSubscribe, onDispose) + .to(TestHelper.testConsumer()) + .assertFailureAndMessage(TestException.class, "First"); + + assertTrue(bs.isDisposed()); + + TestHelper.assertUndeliverable(errors, 0, TestException.class, "Second"); + + verify(onSubscribe).accept(any()); + verify(onDispose, never()).run(); + }); + } + + @Test + public void onDisposeCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + doThrow(new TestException("First")).when(onDispose).run(); + + SingleSubject ss = SingleSubject.create(); + + TestObserver to = ss + .doOnLifecycle(onSubscribe, onDispose) + .test(); + + assertTrue(ss.hasObservers()); + + to.dispose(); + + assertFalse(ss.hasObservers()); + + TestHelper.assertUndeliverable(errors, 0, TestException.class, "First"); + + verify(onSubscribe).accept(any()); + verify(onDispose).run(); + }); + } + + @Test + public void dispose() throws Throwable { + @SuppressWarnings("unchecked") + Consumer onSubscribe = mock(Consumer.class); + Action onDispose = mock(Action.class); + + SingleSubject ss = SingleSubject.create(); + + TestObserver to = ss + .doOnLifecycle(onSubscribe, onDispose) + .test(); + + assertTrue(ss.hasObservers()); + + to.dispose(); + + assertFalse(ss.hasObservers()); + + verify(onSubscribe).accept(any()); + verify(onDispose).run(); + } + + @Test + public void isDisposed() { + TestHelper.checkDisposed(SingleSubject.create().doOnLifecycle(d -> { }, () -> { })); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeSingle(m -> m.doOnLifecycle(d -> { }, () -> { })); + } +} From 57bd1a9272464a1b4b201faa2bab7a929a0ae7f3 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Sun, 26 Jan 2020 20:13:17 +0100 Subject: [PATCH 24/37] 3.x: Add concatMapX operators (aliases) (#6879) --- docs/Operator-Matrix.md | 458 +++++++++--------- .../java/io/reactivex/rxjava3/core/Maybe.java | 70 ++- .../io/reactivex/rxjava3/core/Single.java | 80 +++ .../maybe/MaybeConcatMapCompletableTest.java | 60 +++ .../maybe/MaybeConcatMapSingleTest.java | 142 ++++++ .../operators/maybe/MaybeConcatMapTest.java | 101 ++++ .../SingleConcatMapCompletableTest.java | 114 +++++ .../single/SingleConcatMapMaybeTest.java | 141 ++++++ .../operators/single/SingleConcatMapTest.java | 132 +++++ .../util/OperatorMatrixGenerator.java | 6 + 10 files changed, 1063 insertions(+), 241 deletions(-) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapCompletableTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapSingleTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapCompletableTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapMaybeTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapTest.java diff --git a/docs/Operator-Matrix.md b/docs/Operator-Matrix.md index a44eed94ec..cd71558ddb 100644 --- a/docs/Operator-Matrix.md +++ b/docs/Operator-Matrix.md @@ -37,102 +37,102 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `concatArrayEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([25](#notes-25))| `concatDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| `concatEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([26](#notes-26))| -`concatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `concatMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `concatMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| -`concatMapEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| -`concatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `concatWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `contains`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`count`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))| +`count`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| `create`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`debounce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`defaultIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| +`debounce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`defaultIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| `defer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `delay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `delaySubscription`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`dematerialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`distinct`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`distinctUntilChanged`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`doAfterNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`doAfterSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`dematerialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`distinct`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`distinctUntilChanged`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`doAfterNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`doAfterSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| `doAfterTerminate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `doFinally`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnCancel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))| -`doOnComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnDispose`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`doOnCancel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))| +`doOnComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnDispose`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| `doOnError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnEvent`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnEvent`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `doOnLifecycle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`doOnRequest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| +`doOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`doOnRequest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))| `doOnSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`doOnSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| `doOnTerminate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`elementAt`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`elementAtOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`empty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))| +`elementAt`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`elementAtOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`empty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| `error`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`filter`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`first`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| -`firstElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`firstOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))| -`firstOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))| -`firstStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| +`filter`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`first`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`firstElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`firstOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))| +`firstOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| +`firstStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))| `flatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `flatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapPublisher`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapSingleElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenStreamAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenStreamAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`forEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))| -`forEachWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))| +`flatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapPublisher`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapSingleElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenStreamAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`flattenStreamAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`forEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| +`forEachWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| `fromAction`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| +`fromArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| `fromCallable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))| +`fromCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([76](#notes-76))| `fromCompletionStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `fromFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| -`fromMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| +`fromIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| +`fromMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([76](#notes-76))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([76](#notes-76))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| `fromPublisher`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `fromRunnable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`fromStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| +`fromSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([76](#notes-76))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`fromStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([72](#notes-72))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([73](#notes-73))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| `fromSupplier`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`generate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| -`groupBy`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([76](#notes-76))| -`groupJoin`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([77](#notes-77))| +`generate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([77](#notes-77))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([77](#notes-77))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([77](#notes-77))| +`groupBy`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))| +`groupJoin`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))| `hide`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`ignoreElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`ignoreElements`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([79](#notes-79))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`interval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))| -`intervalRange`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))| -`isEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`join`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([77](#notes-77))| +`ignoreElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([81](#notes-81))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`ignoreElements`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`interval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))| +`intervalRange`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))| +`isEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`join`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))| `just`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`last`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| -`lastElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`lastOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))| -`lastOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))| -`lastStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| +`last`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`lastElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`lastOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))| +`lastOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| +`lastStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))| `lift`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `map`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `mapOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| @@ -144,100 +144,100 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `mergeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `never`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `observeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`ofType`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))| -`onBackpressureBuffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| -`onBackpressureDrop`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| -`onBackpressureLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| +`ofType`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))| +`onBackpressureBuffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))| +`onBackpressureDrop`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))| +`onBackpressureLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))| `onErrorComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `onErrorResumeNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `onErrorResumeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `onErrorReturn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| `onErrorReturnItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| `onTerminateDetach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`parallel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))| -`publish`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| -`range`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| -`rangeLong`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| -`rebatchRequests`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))| -`reduce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| -`reduceWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| +`parallel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| +`publish`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| +`range`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| +`rangeLong`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| +`rebatchRequests`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))| +`reduce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))| +`reduceWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))| `repeat`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `repeatUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `repeatWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`replay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| +`replay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| `retry`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `retryUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `retryWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `safeSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| -`sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`scan`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| -`scanWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| +`sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`scan`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))| +`scanWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))| `sequenceEqual`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| -`serialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))| -`share`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| -`single`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| -`singleElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`singleOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))| -`singleOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))| -`singleStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| -`skip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| -`skipLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| -`skipUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))| -`skipWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`sorted`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([75](#notes-75))| +`serialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))| +`share`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| +`single`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`singleElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`singleOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))| +`singleOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| +`singleStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))| +`skip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| +`skipLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| +`skipUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))| +`skipWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`sorted`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))| `startWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`startWithArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))| -`startWithItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))| -`startWithIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))| +`startWithArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))| +`startWithItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))| +`startWithIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))| `subscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `subscribeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `subscribeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`switchIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))| -`switchMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))| +`switchMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `switchOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `switchOnNextDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`take`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| -`takeLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| +`take`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| +`takeLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| `takeUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`takeWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`takeWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| `test`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`throttleFirst`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`throttleLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`throttleLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`throttleWithTimeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| -`timeInterval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`throttleFirst`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`throttleLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`throttleLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`throttleWithTimeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`timeInterval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| `timeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `timer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))| +`timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| `to`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toCompletionStage`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toCompletionStage`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([101](#notes-101))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([101](#notes-101))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toFuture`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| `toMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| -`toMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toMaybe`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([103](#notes-103))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([103](#notes-103))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toMultimap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| -`toObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([101](#notes-101))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([101](#notes-101))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`toSingleDefault`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([103](#notes-103))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toObservable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toSingle`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([104](#notes-104))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([104](#notes-104))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`toSingleDefault`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([105](#notes-105))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([105](#notes-105))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([106](#notes-106))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toSortedList`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([13](#notes-13))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([14](#notes-14))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([15](#notes-15))| `unsafeCreate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `unsubscribeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `using`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`window`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([104](#notes-104))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([105](#notes-105))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([106](#notes-106))| +`window`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([107](#notes-107))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([108](#notes-108))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([109](#notes-109))| `withLatestFrom`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([16](#notes-16))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([16](#notes-16))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([17](#notes-17))| -`wrap`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([107](#notes-107))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([108](#notes-108))| -`zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([109](#notes-109))| -`zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([110](#notes-110))| -**237 operators** | **215** | **209** | **113** | **97** | **78** | +`wrap`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([110](#notes-110))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([111](#notes-111))| +`zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([112](#notes-112))| +`zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([113](#notes-113))| +**237 operators** | **215** | **209** | **115** | **100** | **78** | #### Notes 1 Use [`contains()`](#contains).
@@ -269,87 +269,90 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat 27 Always empty thus no items to map.
28 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapCompletable`](#concatMapCompletable).
29 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMap`](#concatMap).
-30 At most one item. Use [`flattenAsFlowable`](#flattenAsFlowable) or [`flattenAsObservable`](#flattenAsObservable).
-31 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapMaybe`](#concatMapMaybe).
-32 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapSingle`](#concatMapSingle).
-33 At most one item. Use [`flattenStreamAsFlowable`](#flattenStreamAsFlowable) or [`flattenStreamAsObservable`](#flattenStreamAsObservable).
-34 Never empty thus always 1.
-35 Always empty thus always 0.
-36 At most one item signaled so no subsequent items to work with.
-37 Always empty thus no items to work with.
-38 Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.
-39 At most one item, always distinct.
-40 Different terminology. Use [`doAfterSuccess()`](#doAfterSuccess).
-41 Different terminology. Use [`doAfterNext()`](#doAfterNext).
-42 Different terminology. Use [`doOnDispose()`](#doOnDispose).
-43 Always succeeds or fails, there is no `onComplete` signal.
-44 Different terminology. Use [`doOnCancel()`](#doOnCancel).
-45 At most one item. Use [`doOnEvent()`](#doOnEvent).
-46 Use [`doOnEach()`](#doOnEach).
-47 Different terminology. Use [`doOnSuccess()`](#doOnSuccess).
-48 Backpressure related and not supported outside `Flowable`.
-49 Different terminology. Use [`doOnNext()`](#doOnNext).
-50 At most one item with index 0. Use [`defaultIfEmpty`](#defaultIfEmpty).
-51 Always one item with index 0.
-52 At most one item with index 0. Use [`toSingle`](#toSingle).
-53 Use [`complete()`](#complete).
-54 At most one item. Use [`defaultIfEmpty`](#defaultIfEmpty).
-55 Always one item.
-56 At most one item, would be no-op.
-57 Always one item, would be no-op.
-58 Always empty. Use [`andThen()`](#andThen) and [`error()`](#error).
-59 At most one item. Use [`toCompletionStage()`](#toCompletionStage).
-60 Always empty. Use [`andThen()`](#andThen), [`error()`](#error) and [`toCompletionStage()`](#toCompletionStage).
-61 Use [`flatMap()`](#flatMap).
-62 Not supported. Use [`flatMap`](#flatMap) and [`toFlowable()`](#toFlowable).
-63 Use [`flatMap`](#flatMap).
-64 Not supported. Use [`flatMap`](#flatMap) and [`toObservable()`](#toFlowable).
-65 Use [`flatMapSingle`](#flatMapSingle).
-66 Use [`flatMapIterable()`](#flatMapIterable).
-67 Use [`flatMapStream()`](#flatMapStream).
-68 Use [`subscribe()`](#subscribe).
-69 At most one item. Use [`just()`](#just) or [`empty()`](#empty).
-70 Always one item. Use [`just()`](#just).
-71 Always empty. Use [`complete()`](#complete).
-72 Always error.
-73 Use [`wrap()`](#wrap).
-74 Use [`fromSupplier()`](#fromSupplier).
-75 At most one item.
-76 Always empty thus no items to group.
-77 Always empty thus no items to join.
-78 Use [`ignoreElements()`](#ignoreElements).
-79 Use [`ignoreElement()`](#ignoreElement).
-80 At most one item. Use [`timer()`](#timer).
-81 At most one item. Use [`zip()`](#zip)
-82 Always empty thus no items to filter.
-83 Needs backpressure thus not supported outside `Flowable`.
-84 Connectable sources not supported outside `Flowable` and `Observable`. Use a `MaybeSubject`.
-85 Connectable sources not supported outside `Flowable` and `Observable`. Use a `SingleSubject`.
-86 Connectable sources not supported outside `Flowable` and `Observable`. Use a `ConnectableSubject`.
-87 At most one item. Use [`just()`](#just).
-88 At most one item. Use [`map()`](#map).
-89 Always empty thus no items to reduce.
-90 At most one signal type.
-91 At most one item. Use [`takeUntil()`](#takeUntil).
-92 At most one item. Use [`filter()`](#filter).
-93 Use [`startWith()`](#startWith) and [`fromArray()`](#fromArray) of `Flowable` or `Observable`.
-94 Use [`startWith()`](#startWith) and [`just()`](#just) of another reactive type.
-95 Use [`startWith()`](#startWith) and [`fromIterable()`](#fromArray) of `Flowable` or `Observable`.
-96 Always empty. Use [`defaultIfEmpty()`](#defaultIfEmpty).
-97 At most one item. Use [`flatMap()`](#flatMap).
-98 Use [`firstStage`](#firstStage), [`lastStage`](#lastStage) or [`singleStage`](#singleStage).
-99 Would be no-op.
-100 Use [`firstElement`](#firstElement), [`lastElement`](#lastElement) or [`singleElement`](#singleElement).
-101 Use [`firstOrError`](#firstOrError), [`lastOrError`](#lastOrError) or [`singleOrError`](#singleOrError).
-102 Use [`first`](#first), [`last`](#last) or [`single`](#single).
-103 Use [`defaultIfEmpty()`](#defaultIfEmpty).
-104 Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a nested source.
-105 Use [`map()`](#map) to transform into a nested source.
-106 Always empty. Use [`andThen()`](#andThen) to bring in a nested source.
-107 Use [`fromPublisher()`](#fromPublisher).
-108 Use [`merge()`](#merge).
-109 Use [`mergeArray()`](#mergeArray).
-110 Use [`mergeWith()`](#mergeWith).
+30 At most one item to map. Use [`concatMap()`](#concatMap).
+31 At most one item. Use [`flattenAsFlowable`](#flattenAsFlowable) or [`flattenAsObservable`](#flattenAsObservable).
+32 Use [`concatMap`](#concatMap).
+33 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapMaybe`](#concatMapMaybe).
+34 Use [`concatMap()`](#concatMap).
+35 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapSingle`](#concatMapSingle).
+36 At most one item. Use [`flattenStreamAsFlowable`](#flattenStreamAsFlowable) or [`flattenStreamAsObservable`](#flattenStreamAsObservable).
+37 Never empty thus always 1.
+38 Always empty thus always 0.
+39 At most one item signaled so no subsequent items to work with.
+40 Always empty thus no items to work with.
+41 Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.
+42 At most one item, always distinct.
+43 Different terminology. Use [`doAfterSuccess()`](#doAfterSuccess).
+44 Different terminology. Use [`doAfterNext()`](#doAfterNext).
+45 Different terminology. Use [`doOnDispose()`](#doOnDispose).
+46 Always succeeds or fails, there is no `onComplete` signal.
+47 Different terminology. Use [`doOnCancel()`](#doOnCancel).
+48 At most one item. Use [`doOnEvent()`](#doOnEvent).
+49 Use [`doOnEach()`](#doOnEach).
+50 Different terminology. Use [`doOnSuccess()`](#doOnSuccess).
+51 Backpressure related and not supported outside `Flowable`.
+52 Different terminology. Use [`doOnNext()`](#doOnNext).
+53 At most one item with index 0. Use [`defaultIfEmpty`](#defaultIfEmpty).
+54 Always one item with index 0.
+55 At most one item with index 0. Use [`toSingle`](#toSingle).
+56 Use [`complete()`](#complete).
+57 At most one item. Use [`defaultIfEmpty`](#defaultIfEmpty).
+58 Always one item.
+59 At most one item, would be no-op.
+60 Always one item, would be no-op.
+61 Always empty. Use [`andThen()`](#andThen) and [`error()`](#error).
+62 At most one item. Use [`toCompletionStage()`](#toCompletionStage).
+63 Always empty. Use [`andThen()`](#andThen), [`error()`](#error) and [`toCompletionStage()`](#toCompletionStage).
+64 Use [`flatMap()`](#flatMap).
+65 Not supported. Use [`flatMap`](#flatMap) and [`toFlowable()`](#toFlowable).
+66 Use [`flatMap`](#flatMap).
+67 Not supported. Use [`flatMap`](#flatMap) and [`toObservable()`](#toFlowable).
+68 Use [`flatMapSingle`](#flatMapSingle).
+69 Use [`flatMapIterable()`](#flatMapIterable).
+70 Use [`flatMapStream()`](#flatMapStream).
+71 Use [`subscribe()`](#subscribe).
+72 At most one item. Use [`just()`](#just) or [`empty()`](#empty).
+73 Always one item. Use [`just()`](#just).
+74 Always empty. Use [`complete()`](#complete).
+75 Always error.
+76 Use [`wrap()`](#wrap).
+77 Use [`fromSupplier()`](#fromSupplier).
+78 At most one item.
+79 Always empty thus no items to group.
+80 Always empty thus no items to join.
+81 Use [`ignoreElements()`](#ignoreElements).
+82 Use [`ignoreElement()`](#ignoreElement).
+83 At most one item. Use [`timer()`](#timer).
+84 At most one item. Use [`zip()`](#zip)
+85 Always empty thus no items to filter.
+86 Needs backpressure thus not supported outside `Flowable`.
+87 Connectable sources not supported outside `Flowable` and `Observable`. Use a `MaybeSubject`.
+88 Connectable sources not supported outside `Flowable` and `Observable`. Use a `SingleSubject`.
+89 Connectable sources not supported outside `Flowable` and `Observable`. Use a `ConnectableSubject`.
+90 At most one item. Use [`just()`](#just).
+91 At most one item. Use [`map()`](#map).
+92 Always empty thus no items to reduce.
+93 At most one signal type.
+94 At most one item. Use [`takeUntil()`](#takeUntil).
+95 At most one item. Use [`filter()`](#filter).
+96 Use [`startWith()`](#startWith) and [`fromArray()`](#fromArray) of `Flowable` or `Observable`.
+97 Use [`startWith()`](#startWith) and [`just()`](#just) of another reactive type.
+98 Use [`startWith()`](#startWith) and [`fromIterable()`](#fromArray) of `Flowable` or `Observable`.
+99 Always empty. Use [`defaultIfEmpty()`](#defaultIfEmpty).
+100 At most one item. Use [`flatMap()`](#flatMap).
+101 Use [`firstStage`](#firstStage), [`lastStage`](#lastStage) or [`singleStage`](#singleStage).
+102 Would be no-op.
+103 Use [`firstElement`](#firstElement), [`lastElement`](#lastElement) or [`singleElement`](#singleElement).
+104 Use [`firstOrError`](#firstOrError), [`lastOrError`](#lastOrError) or [`singleOrError`](#singleOrError).
+105 Use [`first`](#first), [`last`](#last) or [`single`](#single).
+106 Use [`defaultIfEmpty()`](#defaultIfEmpty).
+107 Use [`map()`](#map) and [`switchIfEmpty()`](#switchIfEmpty) to transform into a nested source.
+108 Use [`map()`](#map) to transform into a nested source.
+109 Always empty. Use [`andThen()`](#andThen) to bring in a nested source.
+110 Use [`fromPublisher()`](#fromPublisher).
+111 Use [`merge()`](#merge).
+112 Use [`mergeArray()`](#mergeArray).
+113 Use [`mergeWith()`](#mergeWith).
#### Under development @@ -359,26 +362,13 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat 4. Single.concatArrayEagerDelayError() 5. Single.concatDelayError() 6. Completable.concatDelayError() -7. Single.concatMap() -8. Maybe.concatMapCompletable() -9. Single.concatMapCompletable() -10. Maybe.concatMapEager() -11. Single.concatMapEager() -12. Completable.concatMapEager() -13. Maybe.concatMapEagerDelayError() -14. Single.concatMapEagerDelayError() -15. Completable.concatMapEagerDelayError() -16. Maybe.concatMapMaybe() -17. Single.concatMapMaybe() -18. Maybe.concatMapSingle() -19. Single.concatMapSingle() -20. Single.mergeArray() -21. Single.mergeArrayDelayError() -22. Completable.onErrorReturn() -23. Completable.onErrorReturnItem() -24. Maybe.safeSubscribe() -25. Single.safeSubscribe() -26. Completable.safeSubscribe() -27. Completable.sequenceEqual() -28. Maybe.startWith() -29. Single.startWith() +7. Single.mergeArray() +8. Single.mergeArrayDelayError() +9. Completable.onErrorReturn() +10. Completable.onErrorReturnItem() +11. Maybe.safeSubscribe() +12. Single.safeSubscribe() +13. Completable.safeSubscribe() +14. Completable.sequenceEqual() +15. Maybe.startWith() +16. Single.startWith() diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index b3ed8213d4..6754f65e7b 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -2828,12 +2828,13 @@ public final Maybe compose(@NonNull MaybeTransformer - * + * + *

+ * Note that flatMap and concatMap for {@code Maybe} is the same operation. *

*
Scheduler:
*
{@code concatMap} does not operate by default on a particular {@link Scheduler}.
*
- *

Note that flatMap and concatMap for {@code Maybe} is the same operation. * @param the result value type * @param mapper * a function that, when applied to the item emitted by the current {@code Maybe}, returns a {@code MaybeSource} @@ -2845,8 +2846,63 @@ public final Maybe compose(@NonNull MaybeTransformer Maybe concatMap(@NonNull Function> mapper) { - Objects.requireNonNull(mapper, "mapper is null"); - return RxJavaPlugins.onAssembly(new MaybeFlatten<>(this, mapper)); + return flatMap(mapper); + } + + /** + * Returns a {@link Completable} that completes based on applying a specified function to the item emitted by the + * current {@code Maybe}, where that function returns a {@code Completable}. + *

+ * + *

+ * This operator is an alias for {@link #flatMapCompletable(Function)}. + *

+ *
Scheduler:
+ *
{@code concatMapCompletable} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param mapper + * a function that, when applied to the item emitted by the current {@code Maybe}, returns a + * {@code Completable} + * @return the new {@code Completable} instance + * @throws NullPointerException if {@code mapper} is {@code null} + * @see ReactiveX operators documentation: FlatMap + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Completable concatMapCompletable(@NonNull Function mapper) { + return flatMapCompletable(mapper); + } + + /** + * Returns a {@code Maybe} based on applying a specified function to the item emitted by the + * current {@code Maybe}, where that function returns a {@link Single}. + * When this {@code Maybe} just completes the resulting {@code Maybe} completes as well. + *

+ * + *

+ * This operator is an alias for {@link #flatMapSingleElement(Function)}. + *

+ *
Scheduler:
+ *
{@code concatMapSingle} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the result value type + * @param mapper + * a function that, when applied to the item emitted by the current {@code Maybe}, returns a + * {@code Single} + * @return the new {@code Maybe} instance + * @throws NullPointerException if {@code mapper} is {@code null} + * @see ReactiveX operators documentation: FlatMap + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Maybe concatMapSingle(@NonNull Function> mapper) { + return flatMapSingleElement(mapper); } /** @@ -3732,7 +3788,7 @@ public final Flowable flatMapPublisher(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapSingle} does not operate by default on a particular {@link Scheduler}.
@@ -3759,7 +3815,7 @@ public final Single flatMapSingle(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapSingleElement} does not operate by default on a particular {@link Scheduler}.
@@ -3787,7 +3843,7 @@ public final Maybe flatMapSingleElement(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapCompletable} does not operate by default on a particular {@link Scheduler}.
diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 81b0aaaffe..0a1d872b14 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -2278,6 +2278,86 @@ public final Single cast(@NonNull Class clazz) { return map(Functions.castFunction(clazz)); } + /** + * Returns a {@code Single} that is based on applying a specified function to the item emitted by the current {@code Single}, + * where that function returns a {@link SingleSource}. + *

+ * + *

+ * The operator is an alias for {@link #flatMap(Function)} + *

+ *
Scheduler:
+ *
{@code concatMap} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the result value type + * @param mapper + * a function that, when applied to the item emitted by the current {@code Single}, returns a {@code SingleSource} + * @return the new {@code Single} returned from {@code mapper} when applied to the item emitted by the current {@code Single} + * @throws NullPointerException if {@code mapper} is {@code null} + * @see ReactiveX operators documentation: FlatMap + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Single concatMap(@NonNull Function> mapper) { + Objects.requireNonNull(mapper, "mapper is null"); + return RxJavaPlugins.onAssembly(new SingleFlatMap<>(this, mapper)); + } + + /** + * Returns a {@link Completable} that completes based on applying a specified function to the item emitted by the + * current {@code Single}, where that function returns a {@link CompletableSource}. + *

+ * + *

+ * The operator is an alias for {@link #flatMapCompletable(Function)}. + *

+ *
Scheduler:
+ *
{@code concatMapCompletable} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param mapper + * a function that, when applied to the item emitted by the current {@code Single}, returns a + * {@code CompletableSource} + * @return the new {@code Completable} instance + * @throws NullPointerException if {@code mapper} is {@code null} + * @see ReactiveX operators documentation: FlatMap + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Completable concatMapCompletable(@NonNull Function mapper) { + return flatMapCompletable(mapper); + } + + /** + * Returns a {@link Maybe} that is based on applying a specified function to the item emitted by the current {@code Single}, + * where that function returns a {@link MaybeSource}. + *

+ * + *

+ * The operator is an alias for {@link #flatMapMaybe(Function)}. + *

+ *
Scheduler:
+ *
{@code concatMapMaybe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the result value type + * @param mapper + * a function that, when applied to the item emitted by the current {@code Single}, returns a {@code MaybeSource} + * @return the new {@code Maybe} returned from {@code mapper} when applied to the item emitted by the current {@code Single} + * @throws NullPointerException if {@code mapper} is {@code null} + * @see ReactiveX operators documentation: FlatMap + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Maybe concatMapMaybe(@NonNull Function> mapper) { + return flatMapMaybe(mapper); + } + /** * Returns a {@link Flowable} that emits the item emitted by the current {@code Single}, then the item emitted by the * specified {@link SingleSource}. diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapCompletableTest.java new file mode 100644 index 0000000000..e902bbf4df --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapCompletableTest.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class MaybeConcatMapCompletableTest extends RxJavaTest { + + @Test + public void dispose() { + TestHelper.checkDisposed(Maybe.just(1).concatMapCompletable(new Function() { + @Override + public Completable apply(Integer v) throws Exception { + return Completable.complete(); + } + })); + } + + @Test + public void mapperThrows() { + Maybe.just(1) + .concatMapCompletable(new Function() { + @Override + public Completable apply(Integer v) throws Exception { + throw new TestException(); + } + }) + .test() + .assertFailure(TestException.class); + } + + @Test + public void mapperReturnsNull() { + Maybe.just(1) + .concatMapCompletable(new Function() { + @Override + public Completable apply(Integer v) throws Exception { + return null; + } + }) + .test() + .assertFailure(NullPointerException.class); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapSingleTest.java new file mode 100644 index 0000000000..2626b18e26 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapSingleTest.java @@ -0,0 +1,142 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class MaybeConcatMapSingleTest extends RxJavaTest { + @Test + public void flatMapSingleElementValue() { + Maybe.just(1).concatMapSingle(new Function>() { + @Override public SingleSource apply(final Integer integer) throws Exception { + if (integer == 1) { + return Single.just(2); + } + + return Single.just(1); + } + }) + .test() + .assertResult(2); + } + + @Test + public void flatMapSingleElementValueDifferentType() { + Maybe.just(1).concatMapSingle(new Function>() { + @Override public SingleSource apply(final Integer integer) throws Exception { + if (integer == 1) { + return Single.just("2"); + } + + return Single.just("1"); + } + }) + .test() + .assertResult("2"); + } + + @Test + public void flatMapSingleElementValueNull() { + Maybe.just(1).concatMapSingle(new Function>() { + @Override public SingleSource apply(final Integer integer) throws Exception { + return null; + } + }) + .to(TestHelper.testConsumer()) + .assertNoValues() + .assertError(NullPointerException.class) + .assertErrorMessage("The mapper returned a null SingleSource"); + } + + @Test + public void flatMapSingleElementValueErrorThrown() { + Maybe.just(1).concatMapSingle(new Function>() { + @Override public SingleSource apply(final Integer integer) throws Exception { + throw new RuntimeException("something went terribly wrong!"); + } + }) + .to(TestHelper.testConsumer()) + .assertNoValues() + .assertError(RuntimeException.class) + .assertErrorMessage("something went terribly wrong!"); + } + + @Test + public void flatMapSingleElementError() { + RuntimeException exception = new RuntimeException("test"); + + Maybe.error(exception).concatMapSingle(new Function>() { + @Override public SingleSource apply(final Object integer) throws Exception { + return Single.just(new Object()); + } + }) + .test() + .assertError(exception); + } + + @Test + public void flatMapSingleElementEmpty() { + Maybe.empty().concatMapSingle(new Function>() { + @Override public SingleSource apply(final Integer integer) throws Exception { + return Single.just(2); + } + }) + .test() + .assertNoValues() + .assertResult(); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(Maybe.just(1).concatMapSingle(new Function>() { + @Override + public SingleSource apply(final Integer integer) throws Exception { + return Single.just(2); + } + })); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeMaybe(new Function, Maybe>() { + @Override + public Maybe apply(Maybe m) throws Exception { + return m.concatMapSingle(new Function>() { + @Override + public SingleSource apply(final Integer integer) throws Exception { + return Single.just(2); + } + }); + } + }); + } + + @Test + public void singleErrors() { + Maybe.just(1) + .concatMapSingle(new Function>() { + @Override + public SingleSource apply(final Integer integer) throws Exception { + return Single.error(new TestException()); + } + }) + .test() + .assertFailure(TestException.class); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapTest.java new file mode 100644 index 0000000000..7504117df4 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatMapTest.java @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class MaybeConcatMapTest extends RxJavaTest { + + @Test + public void dispose() { + TestHelper.checkDisposed(Maybe.just(1).concatMap(new Function>() { + @Override + public MaybeSource apply(Integer v) throws Exception { + return Maybe.just(2); + } + })); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeMaybe(new Function, MaybeSource>() { + @Override + public MaybeSource apply(Maybe v) throws Exception { + return v.concatMap(new Function>() { + @Override + public MaybeSource apply(Integer v) throws Exception { + return Maybe.just(2); + } + }); + } + }); + } + + @Test + public void mainError() { + Maybe.error(new TestException()) + .concatMap(new Function>() { + @Override + public MaybeSource apply(Integer v) throws Exception { + return Maybe.just(2); + } + }) + .test() + .assertFailure(TestException.class); + } + + @Test + public void mainEmpty() { + Maybe.empty() + .concatMap(new Function>() { + @Override + public MaybeSource apply(Integer v) throws Exception { + return Maybe.just(2); + } + }) + .test() + .assertResult(); + } + + @Test + public void mapperThrows() { + Maybe.just(1) + .concatMap(new Function>() { + @Override + public MaybeSource apply(Integer v) throws Exception { + throw new TestException(); + } + }) + .test() + .assertFailure(TestException.class); + } + + @Test + public void mapperReturnsNull() { + Maybe.just(1) + .concatMap(new Function>() { + @Override + public MaybeSource apply(Integer v) throws Exception { + return null; + } + }) + .test() + .assertFailure(NullPointerException.class); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapCompletableTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapCompletableTest.java new file mode 100644 index 0000000000..1a160f6465 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapCompletableTest.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleConcatMapCompletableTest extends RxJavaTest { + + @Test + public void dispose() { + TestHelper.checkDisposed(Single.just(1).concatMapCompletable(new Function() { + @Override + public Completable apply(Integer v) throws Exception { + return Completable.complete(); + } + })); + } + + @Test + public void normal() { + final boolean[] b = { false }; + + Single.just(1) + .concatMapCompletable(new Function() { + @Override + public Completable apply(Integer t) throws Exception { + return Completable.complete().doOnComplete(new Action() { + @Override + public void run() throws Exception { + b[0] = true; + } + }); + } + }) + .test() + .assertResult(); + + assertTrue(b[0]); + } + + @Test + public void error() { + final boolean[] b = { false }; + + Single.error(new TestException()) + .concatMapCompletable(new Function() { + @Override + public Completable apply(Integer t) throws Exception { + return Completable.complete().doOnComplete(new Action() { + @Override + public void run() throws Exception { + b[0] = true; + } + }); + } + }) + .test() + .assertFailure(TestException.class); + + assertFalse(b[0]); + } + + @Test + public void mapperThrows() { + final boolean[] b = { false }; + + Single.just(1) + .concatMapCompletable(new Function() { + @Override + public Completable apply(Integer t) throws Exception { + throw new TestException(); + } + }) + .test() + .assertFailure(TestException.class); + + assertFalse(b[0]); + } + + @Test + public void mapperReturnsNull() { + final boolean[] b = { false }; + + Single.just(1) + .concatMapCompletable(new Function() { + @Override + public Completable apply(Integer t) throws Exception { + return null; + } + }) + .test() + .assertFailure(NullPointerException.class); + + assertFalse(b[0]); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapMaybeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapMaybeTest.java new file mode 100644 index 0000000000..dd25e7a53f --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapMaybeTest.java @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleConcatMapMaybeTest extends RxJavaTest { + @Test + public void concatMapMaybeValue() { + Single.just(1).concatMapMaybe(new Function>() { + @Override public MaybeSource apply(final Integer integer) throws Exception { + if (integer == 1) { + return Maybe.just(2); + } + + return Maybe.just(1); + } + }) + .test() + .assertResult(2); + } + + @Test + public void concatMapMaybeValueDifferentType() { + Single.just(1).concatMapMaybe(new Function>() { + @Override public MaybeSource apply(final Integer integer) throws Exception { + if (integer == 1) { + return Maybe.just("2"); + } + + return Maybe.just("1"); + } + }) + .test() + .assertResult("2"); + } + + @Test + public void concatMapMaybeValueNull() { + Single.just(1).concatMapMaybe(new Function>() { + @Override public MaybeSource apply(final Integer integer) throws Exception { + return null; + } + }) + .to(TestHelper.testConsumer()) + .assertNoValues() + .assertError(NullPointerException.class) + .assertErrorMessage("The mapper returned a null MaybeSource"); + } + + @Test + public void concatMapMaybeValueErrorThrown() { + Single.just(1).concatMapMaybe(new Function>() { + @Override public MaybeSource apply(final Integer integer) throws Exception { + throw new RuntimeException("something went terribly wrong!"); + } + }) + .to(TestHelper.testConsumer()) + .assertNoValues() + .assertError(RuntimeException.class) + .assertErrorMessage("something went terribly wrong!"); + } + + @Test + public void concatMapMaybeError() { + RuntimeException exception = new RuntimeException("test"); + + Single.error(exception).concatMapMaybe(new Function>() { + @Override public MaybeSource apply(final Object integer) throws Exception { + return Maybe.just(new Object()); + } + }) + .test() + .assertError(exception); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(Single.just(1).concatMapMaybe(new Function>() { + @Override + public MaybeSource apply(Integer v) throws Exception { + return Maybe.just(1); + } + })); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeSingleToMaybe(new Function, MaybeSource>() { + @Override + public MaybeSource apply(Single v) throws Exception { + return v.concatMapMaybe(new Function>() { + @Override + public MaybeSource apply(Integer v) throws Exception { + return Maybe.just(1); + } + }); + } + }); + } + + @Test + public void mapsToError() { + Single.just(1).concatMapMaybe(new Function>() { + @Override + public MaybeSource apply(Integer v) throws Exception { + return Maybe.error(new TestException()); + } + }) + .test() + .assertFailure(TestException.class); + } + + @Test + public void mapsToEmpty() { + Single.just(1).concatMapMaybe(new Function>() { + @Override + public MaybeSource apply(Integer v) throws Exception { + return Maybe.empty(); + } + }) + .test() + .assertResult(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapTest.java new file mode 100644 index 0000000000..b0b5af17a6 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatMapTest.java @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleConcatMapTest extends RxJavaTest { + + @Test + public void concatMapValue() { + Single.just(1).concatMap(new Function>() { + @Override public SingleSource apply(final Integer integer) throws Exception { + if (integer == 1) { + return Single.just(2); + } + + return Single.just(1); + } + }) + .test() + .assertResult(2); + } + + @Test + public void concatMapValueDifferentType() { + Single.just(1).concatMap(new Function>() { + @Override public SingleSource apply(final Integer integer) throws Exception { + if (integer == 1) { + return Single.just("2"); + } + + return Single.just("1"); + } + }) + .test() + .assertResult("2"); + } + + @Test + public void concatMapValueNull() { + Single.just(1).concatMap(new Function>() { + @Override public SingleSource apply(final Integer integer) throws Exception { + return null; + } + }) + .to(TestHelper.testConsumer()) + .assertNoValues() + .assertError(NullPointerException.class) + .assertErrorMessage("The single returned by the mapper is null"); + } + + @Test + public void concatMapValueErrorThrown() { + Single.just(1).concatMap(new Function>() { + @Override public SingleSource apply(final Integer integer) throws Exception { + throw new RuntimeException("something went terribly wrong!"); + } + }) + .to(TestHelper.testConsumer()) + .assertNoValues() + .assertError(RuntimeException.class) + .assertErrorMessage("something went terribly wrong!"); + } + + @Test + public void concatMapError() { + RuntimeException exception = new RuntimeException("test"); + + Single.error(exception).concatMap(new Function>() { + @Override public SingleSource apply(final Object integer) throws Exception { + return Single.just(new Object()); + } + }) + .test() + .assertError(exception); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(Single.just(1).concatMap(new Function>() { + @Override + public SingleSource apply(Integer v) throws Exception { + return Single.just(2); + } + })); + } + + @Test + public void mappedSingleOnError() { + Single.just(1).concatMap(new Function>() { + @Override + public SingleSource apply(Integer v) throws Exception { + return Single.error(new TestException()); + } + }) + .test() + .assertFailure(TestException.class); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeSingle(new Function, SingleSource>() { + @Override + public SingleSource apply(Single s) + throws Exception { + return s.concatMap(new Function>() { + @Override + public SingleSource apply(Object v) + throws Exception { + return Single.just(v); + } + }); + } + }); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java index a0ba3e52e4..0e2c0ada16 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java @@ -240,10 +240,16 @@ static String findNotes(String clazzName, String operatorName) { " C concatMapCompletableDelayError Always empty thus no items to map.", " MS concatMapDelayError Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMap`](#concatMap).", " C concatMapDelayError Always empty thus no items to map.", + " MS concatMapEager At most one item to map. Use [`concatMap()`](#concatMap).", + " C concatMapEager Always empty thus no items to map.", + " MS concatMapEagerDelayError At most one item to map. Use [`concatMap()`](#concatMap).", + " C concatMapEagerDelayError Always empty thus no items to map.", " C concatMapIterable Always empty thus no items to map.", + " M concatMapMaybe Use [`concatMap`](#concatMap).", " C concatMapMaybe Always empty thus no items to map.", " MS concatMapMaybeDelayError Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapMaybe`](#concatMapMaybe).", " C concatMapMaybeDelayError Always empty thus no items to map.", + " S concatMapSingle Use [`concatMap()`](#concatMap).", " C concatMapSingle Always empty thus no items to map.", " MS concatMapSingleDelayError Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapSingle`](#concatMapSingle).", " C concatMapSingleDelayError Always empty thus no items to map.", From 9283700d3a04d495b0845f947ed119c1ed10ee94 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Mon, 27 Jan 2020 11:09:30 +0100 Subject: [PATCH 25/37] 3.x: Add various concatXDelayError operators (#6881) --- docs/Operator-Matrix.md | 34 ++--- .../reactivex/rxjava3/core/Completable.java | 91 +++++++++++ .../java/io/reactivex/rxjava3/core/Maybe.java | 68 ++++++++- .../io/reactivex/rxjava3/core/Single.java | 144 +++++++++++++++++- .../CompletableConcatArrayDelayErrorTest.java | 43 ++++++ .../CompletableConcatDelayErrorTest.java | 82 ++++++++++ .../MaybeConcatArrayEagerDelayErrorTest.java | 34 +++++ .../SingleConcatArrayDelayErrorTest.java | 34 +++++ .../SingleConcatArrayEagerDelayErrorTest.java | 34 +++++ .../single/SingleConcatDelayErrorTest.java | 58 +++++++ .../io/reactivex/rxjava3/maybe/MaybeTest.java | 11 ++ 11 files changed, 605 insertions(+), 28 deletions(-) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArrayDelayErrorTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatDelayErrorTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayEagerDelayErrorTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayDelayErrorTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayEagerDelayErrorTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatDelayErrorTest.java diff --git a/docs/Operator-Matrix.md b/docs/Operator-Matrix.md index cd71558ddb..2ddd1cf21f 100644 --- a/docs/Operator-Matrix.md +++ b/docs/Operator-Matrix.md @@ -32,10 +32,10 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `compose`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `concat`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `concatArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`concatArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`concatArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `concatArrayEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([24](#notes-24))| -`concatArrayEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([25](#notes-25))| -`concatDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`concatArrayEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([25](#notes-25))| +`concatDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `concatEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([26](#notes-26))| `concatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `concatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| @@ -237,7 +237,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([111](#notes-111))| `zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([112](#notes-112))| `zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([113](#notes-113))| -**237 operators** | **215** | **209** | **115** | **100** | **78** | +**237 operators** | **215** | **209** | **116** | **103** | **80** | #### Notes 1 Use [`contains()`](#contains).
@@ -356,19 +356,13 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat #### Under development -1. Single.concatArrayDelayError() -2. Completable.concatArrayDelayError() -3. Maybe.concatArrayEagerDelayError() -4. Single.concatArrayEagerDelayError() -5. Single.concatDelayError() -6. Completable.concatDelayError() -7. Single.mergeArray() -8. Single.mergeArrayDelayError() -9. Completable.onErrorReturn() -10. Completable.onErrorReturnItem() -11. Maybe.safeSubscribe() -12. Single.safeSubscribe() -13. Completable.safeSubscribe() -14. Completable.sequenceEqual() -15. Maybe.startWith() -16. Single.startWith() +1. Single.mergeArray() +2. Single.mergeArrayDelayError() +3. Completable.onErrorReturn() +4. Completable.onErrorReturnItem() +5. Maybe.safeSubscribe() +6. Single.safeSubscribe() +7. Completable.safeSubscribe() +8. Completable.sequenceEqual() +9. Maybe.startWith() +10. Single.startWith() diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 9febbd1204..253610ef80 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -202,6 +202,27 @@ public static Completable concatArray(@NonNull CompletableSource... sources) { return RxJavaPlugins.onAssembly(new CompletableConcatArray(sources)); } + /** + * Returns a {@code Completable} which completes only when all sources complete, one after another. + *

+ * + *

+ *
Scheduler:
+ *
{@code concatArrayDelayError} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param sources the sources to concatenate + * @return the new {@code Completable} instance + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @SafeVarargs + public static Completable concatArrayDelayError(@NonNull CompletableSource... sources) { + return Flowable.fromArray(sources).concatMapCompletableDelayError(Functions.identity(), true, 2); + } + /** * Returns a {@code Completable} which completes only when all sources complete, one after another. *

@@ -273,6 +294,76 @@ public static Completable concat(@NonNull Publisher<@NonNull ? extends Completab return RxJavaPlugins.onAssembly(new CompletableConcat(sources, prefetch)); } + /** + * Returns a {@code Completable} which completes only when all sources complete, one after another. + *

+ * + *

+ *
Scheduler:
+ *
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param sources the sources to concatenate + * @return the new {@code Completable} instance + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Completable concatDelayError(@NonNull Iterable<@NonNull ? extends CompletableSource> sources) { + return Flowable.fromIterable(sources).concatMapCompletableDelayError(Functions.identity()); + } + + /** + * Returns a {@code Completable} which completes only when all sources complete, one after another. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Completable} honors the backpressure of the downstream consumer + * and expects the other {@link Publisher} to honor it as well.
+ *
Scheduler:
+ *
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param sources the sources to concatenate + * @return the new {@code Completable} instance + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + @NonNull + public static Completable concatDelayError(@NonNull Publisher<@NonNull ? extends CompletableSource> sources) { + return concatDelayError(sources, 2); + } + + /** + * Returns a {@code Completable} which completes only when all sources complete, one after another. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Completable} honors the backpressure of the downstream consumer + * and expects the other {@link Publisher} to honor it as well.
+ *
Scheduler:
+ *
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param sources the sources to concatenate + * @param prefetch the number of sources to prefetch from the sources + * @return the new {@code Completable} instance + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code prefetch} is non-positive + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public static Completable concatDelayError(@NonNull Publisher<@NonNull ? extends CompletableSource> sources, int prefetch) { + return Flowable.fromPublisher(sources).concatMapCompletableDelayError(Functions.identity(), true, prefetch); + } + /** * Provides an API (via a cold {@code Completable}) that bridges the reactive world with the callback-style world. *

diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 6754f65e7b..ce02849d56 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -446,13 +446,42 @@ public static Flowable concatArrayDelayError(@NonNull MaybeSource Flowable concatArrayEager(@NonNull MaybeSource... sources) { return Flowable.fromArray(sources).concatMapEager((Function)MaybeToPublisher.instance()); } + /** + * Concatenates a sequence of {@link MaybeSource} eagerly into a {@link Flowable} sequence. + *

+ * Eager concatenation means that once an observer subscribes, this operator subscribes to all of the + * source {@code MaybeSource}s. The operator buffers the value emitted by these {@code MaybeSource}s and then drains them + * in order, each one after the previous one completes. + *

+ * + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream.
+ *
Scheduler:
+ *
This method does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the value type + * @param sources a sequence of {@code MaybeSource}s that need to be eagerly concatenated + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + @SafeVarargs + public static Flowable concatArrayEagerDelayError(@NonNull MaybeSource... sources) { + return Flowable.fromArray(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), true); + } /** * Concatenates the {@link Iterable} sequence of {@link MaybeSource}s into a single sequence by subscribing to each {@code MaybeSource}, * one after the other, one at a time and delays any errors till the all inner {@code MaybeSource}s terminate * as a {@link Flowable} sequence. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream.
@@ -465,14 +494,12 @@ public static Flowable concatArrayEager(@NonNull MaybeSource * @return the new {@code Flowable} with the concatenating behavior * @throws NullPointerException if {@code sources} is {@code null} */ - @SuppressWarnings({ "unchecked", "rawtypes" }) @BackpressureSupport(BackpressureKind.FULL) @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) public static Flowable concatDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { - Objects.requireNonNull(sources, "sources is null"); - return Flowable.fromIterable(sources).concatMapDelayError((Function)MaybeToPublisher.instance()); + return Flowable.fromIterable(sources).concatMapMaybeDelayError(Functions.identity()); } /** @@ -493,13 +520,42 @@ public static Flowable concatDelayError(@NonNull Iterable<@NonNull ? exte * @return the new {@code Flowable} with the concatenating behavior * @throws NullPointerException if {@code sources} is {@code null} */ - @SuppressWarnings({ "unchecked", "rawtypes" }) @BackpressureSupport(BackpressureKind.FULL) @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { - return Flowable.fromPublisher(sources).concatMapDelayError((Function)MaybeToPublisher.instance()); + return Flowable.fromPublisher(sources).concatMapMaybeDelayError(Functions.identity()); + } + /** + * Concatenates the {@link Publisher} sequence of {@link MaybeSource}s into a single sequence by subscribing to each inner {@code MaybeSource}, + * one after the other, one at a time and delays any errors till the all inner and the outer {@code Publisher} terminate + * as a {@link Flowable} sequence. + *

+ * + *

+ *
Backpressure:
+ *
{@code concatDelayError} fully supports backpressure.
+ *
Scheduler:
+ *
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the common element base type + * @param sources the {@code Publisher} sequence of {@code MaybeSource}s + * @param prefetch The number of upstream items to prefetch so that fresh items are + * ready to be mapped when a previous {@code MaybeSource} terminates. + * The operator replenishes after half of the prefetch amount has been consumed + * and turned into {@code MaybeSource}s. + * @return the new {@code Flowable} with the concatenating behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code prefetch} is non-positive + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int prefetch) { + return Flowable.fromPublisher(sources).concatMapMaybeDelayError(Functions.identity(), true, prefetch); } /** diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 0a1d872b14..9f5c3446c5 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -406,10 +406,35 @@ public static Flowable concat( @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - @SuppressWarnings({ "unchecked", "rawtypes" }) @SafeVarargs public static Flowable concatArray(@NonNull SingleSource... sources) { - return RxJavaPlugins.onAssembly(new FlowableConcatMap(Flowable.fromArray(sources), SingleInternalHelper.toFlowable(), 2, ErrorMode.BOUNDARY)); + return Flowable.fromArray(sources).concatMap(SingleInternalHelper.toFlowable(), 2); + } + + /** + * Concatenate the single values, in a non-overlapping fashion, of the {@link SingleSource}s provided in + * an array. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@link Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code concatArrayDelayError} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the value type + * @param sources the array of {@code SingleSource} instances + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.FULL) + @SchedulerSupport(SchedulerSupport.NONE) + @SafeVarargs + public static Flowable concatArrayDelayError(@NonNull SingleSource... sources) { + return Flowable.fromArray(sources).concatMapDelayError(SingleInternalHelper.toFlowable(), true, 2); } /** @@ -440,6 +465,35 @@ public static Flowable concatArrayEager(@NonNull SingleSource + * + *

+ * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * source {@code SingleSource}s. The operator buffers the value emitted by these {@code SingleSource}s and then drains them + * in order, each one after the previous one succeeds. + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream.
+ *
Scheduler:
+ *
This method does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the value type + * @param sources a sequence of {@code SingleSource}s that need to be eagerly concatenated + * @return the new {@link Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @SafeVarargs + public static Flowable concatArrayEagerDelayError(@NonNull SingleSource... sources) { + return Flowable.fromArray(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), true); + } + /** * Concatenates a {@link Publisher} sequence of {@link SingleSource}s eagerly into a single stream of values. *

@@ -469,6 +523,92 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends return Flowable.fromPublisher(sources).concatMapEager(SingleInternalHelper.toFlowable()); } + /** + * Concatenates the {@link Iterable} sequence of {@link SingleSource}s into a single sequence by subscribing to each {@code SingleSource}, + * one after the other, one at a time and delays any errors till the all inner {@code SingleSource}s terminate + * as a {@link Flowable} sequence. + *

+ * + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream.
+ *
Scheduler:
+ *
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the common element base type + * @param sources the {@code Iterable} sequence of {@code SingleSource}s + * @return the new {@code Flowable} with the concatenating behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Flowable concatDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { + return Flowable.fromIterable(sources).concatMapSingleDelayError(Functions.identity()); + } + + /** + * Concatenates the {@link Publisher} sequence of {@link SingleSource}s into a single sequence by subscribing to each inner {@code SingleSource}, + * one after the other, one at a time and delays any errors till the all inner and the outer {@code Publisher} terminate + * as a {@link Flowable} sequence. + *

+ * + *

+ *
Backpressure:
+ *
{@code concatDelayError} fully supports backpressure.
+ *
Scheduler:
+ *
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the common element base type + * @param sources the {@code Publisher} sequence of {@code SingleSource}s + * @return the new {@code Flowable} with the concatenating behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + return Flowable.fromPublisher(sources).concatMapSingleDelayError(Functions.identity()); + } + + /** + * Concatenates the {@link Publisher} sequence of {@link SingleSource}s into a single sequence by subscribing to each inner {@code SingleSource}, + * one after the other, one at a time and delays any errors till the all inner and the outer {@code Publisher} terminate + * as a {@link Flowable} sequence. + *

+ * + *

+ *
Backpressure:
+ *
{@code concatDelayError} fully supports backpressure.
+ *
Scheduler:
+ *
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the common element base type + * @param sources the {@code Publisher} sequence of {@code SingleSource}s + * @param prefetch The number of upstream items to prefetch so that fresh items are + * ready to be mapped when a previous {@code SingleSource} terminates. + * The operator replenishes after half of the prefetch amount has been consumed + * and turned into {@code SingleSource}s. + * @return the new {@code Flowable} with the concatenating behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code prefetch} is non-positive + * @since 3.0.0 + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int prefetch) { + return Flowable.fromPublisher(sources).concatMapSingleDelayError(Functions.identity(), true, prefetch); + } + /** * Concatenates an {@link Iterable} sequence of {@link SingleSource}s eagerly into a single stream of values. *

diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArrayDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArrayDelayErrorTest.java new file mode 100644 index 0000000000..229d00acc6 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatArrayDelayErrorTest.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.completable; + +import static org.mockito.Mockito.*; +import org.junit.Test; + +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Action; + +public class CompletableConcatArrayDelayErrorTest { + + @Test + public void normal() throws Throwable { + Action action1 = mock(Action.class); + Action action2 = mock(Action.class); + + Completable.concatArrayDelayError( + Completable.fromAction(action1), + Completable.error(new TestException()), + Completable.fromAction(action2) + ) + .test() + .assertFailure(TestException.class); + + verify(action1).run(); + + verify(action2).run(); + } + +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatDelayErrorTest.java new file mode 100644 index 0000000000..fd3124a96c --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableConcatDelayErrorTest.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.completable; + +import static org.mockito.Mockito.*; + +import java.util.Arrays; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.Action; + +public class CompletableConcatDelayErrorTest { + + @Test + public void normalIterable() throws Throwable { + Action action1 = mock(Action.class); + Action action2 = mock(Action.class); + + Completable.concatDelayError(Arrays.asList( + Completable.fromAction(action1), + Completable.error(new TestException()), + Completable.fromAction(action2) + )) + .test() + .assertFailure(TestException.class); + + verify(action1).run(); + + verify(action2).run(); + } + + @Test + public void normalPublisher() throws Throwable { + Action action1 = mock(Action.class); + Action action2 = mock(Action.class); + + Completable.concatDelayError(Flowable.fromArray( + Completable.fromAction(action1), + Completable.error(new TestException()), + Completable.fromAction(action2) + )) + .test() + .assertFailure(TestException.class); + + verify(action1).run(); + + verify(action2).run(); + } + + @Test + public void normalPublisherPrefetch() throws Throwable { + Action action1 = mock(Action.class); + Action action2 = mock(Action.class); + + Completable.concatDelayError(Flowable.fromArray( + Completable.fromAction(action1), + Completable.error(new TestException()), + Completable.fromAction(action2) + ), 1) + .test() + .assertFailure(TestException.class); + + verify(action1).run(); + + verify(action2).run(); + } + +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayEagerDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayEagerDelayErrorTest.java new file mode 100644 index 0000000000..6608fbc424 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatArrayEagerDelayErrorTest.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Maybe; +import io.reactivex.rxjava3.exceptions.TestException; + +public class MaybeConcatArrayEagerDelayErrorTest { + + @Test + public void normal() { + Maybe.concatArrayEagerDelayError( + Maybe.just(1), + Maybe.error(new TestException()), + Maybe.empty(), + Maybe.just(2) + ) + .test() + .assertFailure(TestException.class, 1, 2); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayDelayErrorTest.java new file mode 100644 index 0000000000..10fec20410 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayDelayErrorTest.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.exceptions.TestException; + +public class SingleConcatArrayDelayErrorTest { + + @Test + public void normal() { + Single.concatArrayDelayError( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + ) + .test() + .assertFailure(TestException.class, 1, 2); + } + +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayEagerDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayEagerDelayErrorTest.java new file mode 100644 index 0000000000..ce0df373bb --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatArrayEagerDelayErrorTest.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.exceptions.TestException; + +public class SingleConcatArrayEagerDelayErrorTest { + + @Test + public void normal() { + Single.concatArrayEagerDelayError( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + ) + .test() + .assertFailure(TestException.class, 1, 2); + } + +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatDelayErrorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatDelayErrorTest.java new file mode 100644 index 0000000000..83ae9cbf9e --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatDelayErrorTest.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import java.util.Arrays; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class SingleConcatDelayErrorTest { + + @Test + public void normalIterable() { + Single.concatDelayError(Arrays.asList( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + )) + .test() + .assertFailure(TestException.class, 1, 2); + } + + @Test + public void normalPublisher() { + Single.concatDelayError(Flowable.fromArray( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + )) + .test() + .assertFailure(TestException.class, 1, 2); + } + + @Test + public void normalPublisherPrefetch() { + Single.concatDelayError(Flowable.fromArray( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + ), 1) + .test() + .assertFailure(TestException.class, 1, 2); + } + +} diff --git a/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java b/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java index 7a0fe1ae7d..94cf62d641 100644 --- a/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java @@ -2388,6 +2388,17 @@ public void concatPublisherDelayError() { .assertFailure(TestException.class, 1); } + @Test + public void concatPublisherDelayErrorPrefetch() { + Maybe.concatDelayError(Flowable.just(Maybe.empty(), Maybe.just(1), Maybe.error(new TestException())), 1) + .test() + .assertFailure(TestException.class, 1); + + Maybe.concatDelayError(Flowable.just(Maybe.error(new TestException()), Maybe.empty(), Maybe.just(1)), 1) + .test() + .assertFailure(TestException.class, 1); + } + @Test public void concatEagerArray() { PublishProcessor pp1 = PublishProcessor.create(); From 78c70d6a5365cb8db532d23397d5a0b4c114b72a Mon Sep 17 00:00:00 2001 From: David Karnok Date: Mon, 27 Jan 2020 12:42:57 +0100 Subject: [PATCH 26/37] 3.x: Add Single.mergeArray & mergeArrayDelayError (#6882) * 3.x: Add Single.mergeArray & mergeArrayDelayError * Remove unnecessary shortcut --- .../java/io/reactivex/rxjava3/core/Maybe.java | 6 +- .../io/reactivex/rxjava3/core/Single.java | 77 ++++++++++++++++++- .../CancellableQueueFuseableTest.java | 4 +- .../single/SingleMergeArrayTest.java | 50 ++++++++++++ 4 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeArrayTest.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index ce02849d56..5e676681ff 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -1415,7 +1415,7 @@ public static Flowable merge( } /** - * Merges an array sequence of {@link MaybeSource} instances into a single {@link Flowable} sequence, + * Merges an array of {@link MaybeSource} instances into a single {@link Flowable} sequence, * running all {@code MaybeSource}s at once. *

* @@ -1470,10 +1470,10 @@ public static Flowable mergeArray(MaybeSource... sources) { * *

* This behaves like {@link #merge(Publisher)} except that if any of the merged {@code MaybeSource}s notify of an - * error via {@link Subscriber#onError onError}, {@code mergeDelayError} will refrain from propagating that + * error via {@link Subscriber#onError onError}, {@code mergeArrayDelayError} will refrain from propagating that * error notification until all of the merged {@code MaybeSource}s have finished emitting items. *

- * Even if multiple merged {@code MaybeSource}s send {@code onError} notifications, {@code mergeDelayError} will only + * Even if multiple merged {@code MaybeSource}s send {@code onError} notifications, {@code mergeArrayDelayError} will only * invoke the {@code onError} method of its subscribers once. *

*
Backpressure:
diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 9f5c3446c5..5e9b084ad2 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -17,7 +17,7 @@ import java.util.concurrent.*; import java.util.stream.*; -import org.reactivestreams.Publisher; +import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; import io.reactivex.rxjava3.disposables.Disposable; @@ -1323,6 +1323,81 @@ public static Flowable merge( return merge(Flowable.fromArray(source1, source2, source3, source4)); } + /** + * Merges an array of {@link SingleSource} instances into a single {@link Flowable} sequence, + * running all {@code SingleSource}s at once. + *

+ * + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream.
+ *
Scheduler:
+ *
{@code mergeArray} does not operate by default on a particular {@link Scheduler}.
+ *
Error handling:
+ *
If any of the source {@code SingleSource}s signal a {@link Throwable} via {@code onError}, the resulting + * {@code Flowable} terminates with that {@code Throwable} and all other source {@code SingleSource}s are disposed. + * If more than one {@code SingleSource} signals an error, the resulting {@code Flowable} may terminate with the + * first one's error or, depending on the concurrency of the sources, may terminate with a + * {@link CompositeException} containing two or more of the various error signals. + * {@code Throwable}s that didn't make into the composite will be sent (individually) to the global error handler via + * {@link RxJavaPlugins#onError(Throwable)} method as {@link UndeliverableException} errors. Similarly, {@code Throwable}s + * signaled by source(s) after the returned {@code Flowable} has been cancelled or terminated with a + * (composite) error will be sent to the same global error handler. + * Use {@link #mergeArrayDelayError(SingleSource...)} to merge sources and terminate only when all source {@code SingleSource}s + * have completed or failed with an error. + *
+ *
+ * @param the common and resulting value type + * @param sources the array sequence of {@code SingleSource} sources + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code sources} is {@code null} + * @see #mergeArrayDelayError(SingleSource...) + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @SafeVarargs + public static Flowable mergeArray(SingleSource... sources) { + return Flowable.fromArray(sources).flatMapSingle(Functions.identity(), false, sources.length); + } + + /** + * Flattens an array of {@link SingleSource}s into one {@link Flowable}, in a way that allows a subscriber to receive all + * successfully emitted items from each of the source {@code SingleSource}s without being interrupted by an error + * notification from one of them. + *

+ * + *

+ * This behaves like {@link #merge(Publisher)} except that if any of the merged {@code SingleSource}s notify of an + * error via {@link Subscriber#onError onError}, {@code mergeArrayDelayError} will refrain from propagating that + * error notification until all of the merged {@code SingleSource}s have finished emitting items. + *

+ * Even if multiple merged {@code SingleSource}s send {@code onError} notifications, {@code mergeArrayDelayError} will only + * invoke the {@code onError} method of its subscribers once. + *

+ *
Backpressure:
+ *
The operator honors backpressure from downstream.
+ *
Scheduler:
+ *
{@code mergeArrayDelayError} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the common element base type + * @param sources + * the array of {@code SingleSource}s + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code sources} is {@code null} + * @see ReactiveX operators documentation: Merge + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @SafeVarargs + @NonNull + public static Flowable mergeArrayDelayError(@NonNull SingleSource... sources) { + return Flowable.fromArray(sources).flatMapSingle(Functions.identity(), true, sources.length); + } + /** * Merges an {@link Iterable} sequence of {@link SingleSource} instances into one {@link Flowable} sequence, * running all {@code SingleSource}s at once and delaying any error(s) until all sources succeed or fail. diff --git a/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java b/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java index ed4718fd1c..e87bfd315a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/fuseable/CancellableQueueFuseableTest.java @@ -57,7 +57,7 @@ public void dispose() { @Test public void cancel2() { - AbstractEmptyQueueFuseable qs = new AbstractEmptyQueueFuseable() {}; + AbstractEmptyQueueFuseable qs = new AbstractEmptyQueueFuseable() { }; assertFalse(qs.isDisposed()); @@ -66,7 +66,7 @@ public void cancel2() { @Test public void dispose2() { - AbstractEmptyQueueFuseable qs = new AbstractEmptyQueueFuseable() {}; + AbstractEmptyQueueFuseable qs = new AbstractEmptyQueueFuseable() { }; assertFalse(qs.isDisposed()); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeArrayTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeArrayTest.java new file mode 100644 index 0000000000..9434a4fcc1 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleMergeArrayTest.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class SingleMergeArrayTest extends RxJavaTest { + + @Test + public void normal() { + Single.mergeArray(Single.just(1), Single.just(2), Single.just(3)) + .test() + .assertResult(1, 2, 3); + } + + @Test + public void error() { + Single.mergeArray(Single.just(1), Single.error(new TestException()), Single.just(3)) + .test() + .assertFailure(TestException.class, 1); + } + + @Test + public void normalDelayError() { + Single.mergeArrayDelayError(Single.just(1), Single.just(2), Single.just(3)) + .test() + .assertResult(1, 2, 3); + } + + @Test + public void errorDelayError() { + Single.mergeArrayDelayError(Single.just(1), Single.error(new TestException()), Single.just(3)) + .test() + .assertFailure(TestException.class, 1, 3); + } +} From c4d995d57dce44c52f2e687689752cacaae8ec8f Mon Sep 17 00:00:00 2001 From: David Karnok Date: Mon, 27 Jan 2020 15:30:22 +0100 Subject: [PATCH 27/37] 3.x: Add Completable.sequenceEqual (#6884) --- .../reactivex/rxjava3/core/Completable.java | 25 ++++++++++- .../CompletableSequenceEqualTest.java | 43 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSequenceEqualTest.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 253610ef80..e1787b9b46 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -29,7 +29,7 @@ import io.reactivex.rxjava3.internal.operators.completable.*; import io.reactivex.rxjava3.internal.operators.maybe.*; import io.reactivex.rxjava3.internal.operators.mixed.*; -import io.reactivex.rxjava3.internal.operators.single.SingleDelayWithCompletable; +import io.reactivex.rxjava3.internal.operators.single.*; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -414,6 +414,29 @@ public static Completable create(@NonNull CompletableOnSubscribe source) { return RxJavaPlugins.onAssembly(new CompletableCreate(source)); } + /** + * Compares two {@link CompletableSource}s and emits {@code true} via a {@link Single} if both complete. + *

+ * + *

+ *
Scheduler:
+ *
{@code sequenceEqual} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param source1 the first {@code CompletableSource} instance + * @param source2 the second {@code CompletableSource} instance + * @return the new {@code Single} instance + * @throws NullPointerException if {@code source1} or {@code source2} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Single sequenceEqual(@NonNull CompletableSource source1, @NonNull CompletableSource source2) { // NOPMD + Objects.requireNonNull(source1, "source1 is null"); + Objects.requireNonNull(source2, "source2 is null"); + return mergeArrayDelayError(source1, source2).andThen(Single.just(true)); + } + /** * Constructs a {@code Completable} instance by wrapping the given source callback * without any safeguards; you should manage the lifecycle and response diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSequenceEqualTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSequenceEqualTest.java new file mode 100644 index 0000000000..b7b68ad321 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSequenceEqualTest.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.completable; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.exceptions.TestException; + +public class CompletableSequenceEqualTest { + + @Test + public void bothComplete() { + Completable.sequenceEqual(Completable.complete(), Completable.complete()) + .test() + .assertResult(true); + } + + @Test + public void firstFails() { + Completable.sequenceEqual(Completable.error(new TestException()), Completable.complete()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void secondFails() { + Completable.sequenceEqual(Completable.complete(), Completable.error(new TestException())) + .test() + .assertFailure(TestException.class); + } +} From f86753aa4c15717740556ec34418e86edea1b146 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Mon, 27 Jan 2020 15:48:37 +0100 Subject: [PATCH 28/37] 3.x: Add missing startWith overloads (#6885) * 3.x: Add missing startWith overloads * Fix Javadocs copy-paste mistakes --- .../reactivex/rxjava3/core/Completable.java | 59 +++++- .../io/reactivex/rxjava3/core/Flowable.java | 75 +++++++ .../java/io/reactivex/rxjava3/core/Maybe.java | 124 +++++++++++ .../io/reactivex/rxjava3/core/Observable.java | 66 ++++++ .../io/reactivex/rxjava3/core/Single.java | 124 +++++++++++ .../completable/CompletableStartWithTest.java | 67 ++++++ .../flowable/FlowableStartWithTest.java | 153 ++++++++++++++ .../operators/maybe/MaybeStartWithTest.java | 197 ++++++++++++++++++ .../observable/ObservableStartWithTest.java | 153 ++++++++++++++ .../operators/single/SingleStartWithTest.java | 126 +++++++++++ 10 files changed, 1141 insertions(+), 3 deletions(-) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableStartWithTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableStartWithTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeStartWithTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableStartWithTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleStartWithTest.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index e1787b9b46..2ab23028bd 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -2595,7 +2595,7 @@ public final Completable retryWhen(@NonNull Function /** * Returns a {@code Completable} which first runs the other {@link CompletableSource} - * then this {@code Completable} if the other completed normally. + * then the current {@code Completable} if the other completed normally. *

* *

@@ -2614,9 +2614,61 @@ public final Completable startWith(@NonNull CompletableSource other) { return concatArray(other, this); } + /** + * Returns a {@link Flowable} which first runs the other {@link SingleSource} + * then the current {@code Completable} if the other succeeded normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the element type of the {@code other} {@code SingleSource}. + * @param other the other {@code SingleSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull SingleSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Single.wrap(other).toFlowable(), toFlowable()); + } + + /** + * Returns a {@link Flowable} which first runs the other {@link MaybeSource} + * then the current {@code Completable} if the other succeeded or completed normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param the element type of the {@code other} {@code MaybeSource}. + * @param other the other {@code MaybeSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull MaybeSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Maybe.wrap(other).toFlowable(), toFlowable()); + } + /** * Returns an {@link Observable} which first delivers the events - * of the other {@link ObservableSource} then runs this {@code Completable}. + * of the other {@link ObservableSource} then runs the current {@code Completable}. *

* *

@@ -2635,9 +2687,10 @@ public final Observable startWith(@NonNull ObservableSource other) { Objects.requireNonNull(other, "other is null"); return Observable.wrap(other).concatWith(this.toObservable()); } + /** * Returns a {@link Flowable} which first delivers the events - * of the other {@link Publisher} then runs this {@code Completable}. + * of the other {@link Publisher} then runs the current {@code Completable}. *

* *

diff --git a/src/main/java/io/reactivex/rxjava3/core/Flowable.java b/src/main/java/io/reactivex/rxjava3/core/Flowable.java index a994e526c5..453c9e4bba 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Flowable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Flowable.java @@ -15238,6 +15238,81 @@ public final Flowable startWithIterable(@NonNull Iterable<@NonNull ? extends return concatArray(fromIterable(items), this); } + /** + * Returns a {@code Flowable} which first runs the other {@link CompletableSource} + * then the current {@code Flowable} if the other completed normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code CompletableSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull CompletableSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Completable.wrap(other).toFlowable(), this); + } + + /** + * Returns a {@code Flowable} which first runs the other {@link SingleSource} + * then the current {@code Flowable} if the other succeeded normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code SingleSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull SingleSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Single.wrap(other).toFlowable(), this); + } + + /** + * Returns a {@code Flowable} which first runs the other {@link MaybeSource} + * then the current {@code Flowable} if the other succeeded or completed normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code MaybeSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull MaybeSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Maybe.wrap(other).toFlowable(), this); + } + /** * Returns a {@code Flowable} that emits the items in a specified {@link Publisher} before it begins to emit * items emitted by the current {@code Flowable}. diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 5e676681ff..96ff14c1e9 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -20,6 +20,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; +import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; @@ -4859,6 +4860,129 @@ public final Maybe retryWhen( return toFlowable().retryWhen(handler).singleElement(); } + /** + * Returns a {@link Flowable} which first runs the other {@link CompletableSource} + * then the current {@code Maybe} if the other completed normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code CompletableSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull CompletableSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Completable.wrap(other).toFlowable(), toFlowable()); + } + + /** + * Returns a {@link Flowable} which first runs the other {@link SingleSource} + * then the current {@code Maybe} if the other succeeded normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code SingleSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull SingleSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Single.wrap(other).toFlowable(), toFlowable()); + } + + /** + * Returns a {@link Flowable} which first runs the other {@link MaybeSource} + * then the current {@code Maybe} if the other succeeded or completed normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code MaybeSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull MaybeSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Maybe.wrap(other).toFlowable(), toFlowable()); + } + + /** + * Returns an {@link Observable} which first delivers the events + * of the other {@link ObservableSource} then runs the current {@code Maybe}. + *

+ * + *

+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code ObservableSource} to run first + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Observable startWith(@NonNull ObservableSource other) { + Objects.requireNonNull(other, "other is null"); + return Observable.wrap(other).concatWith(this.toObservable()); + } + + /** + * Returns a {@link Flowable} which first delivers the events + * of the other {@link Publisher} then runs the current {@code Maybe}. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer + * and expects the other {@code Publisher} to honor it as well.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code Publisher} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.FULL) + @SchedulerSupport(SchedulerSupport.NONE) + public final Flowable startWith(@NonNull Publisher other) { + Objects.requireNonNull(other, "other is null"); + return toFlowable().startWith(other); + } + /** * Subscribes to a {@code Maybe} and ignores {@code onSuccess} and {@code onComplete} emissions. *

diff --git a/src/main/java/io/reactivex/rxjava3/core/Observable.java b/src/main/java/io/reactivex/rxjava3/core/Observable.java index 3ab0be1ab9..6db7ce3cc1 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Observable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Observable.java @@ -12704,6 +12704,72 @@ public final Observable startWithIterable(@NonNull Iterable<@NonNull ? extend return concatArray(fromIterable(items), this); } + /** + * Returns an {@code Observable} which first runs the other {@link CompletableSource} + * then the current {@code Observable} if the other completed normally. + *

+ * + *

+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code CompletableSource} to run first + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Observable startWith(@NonNull CompletableSource other) { + Objects.requireNonNull(other, "other is null"); + return Observable.concat(Completable.wrap(other).toObservable(), this); + } + + /** + * Returns an {@code Observable} which first runs the other {@link SingleSource} + * then the current {@code Observable} if the other succeeded normally. + *

+ * + *

+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code SingleSource} to run first + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Observable startWith(@NonNull SingleSource other) { + Objects.requireNonNull(other, "other is null"); + return Observable.concat(Single.wrap(other).toObservable(), this); + } + + /** + * Returns an {@code Observable} which first runs the other {@link MaybeSource} + * then the current {@code Observable} if the other succeeded or completed normally. + *

+ * + *

+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code MaybeSource} to run first + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Observable startWith(@NonNull MaybeSource other) { + Objects.requireNonNull(other, "other is null"); + return Observable.concat(Maybe.wrap(other).toObservable(), this); + } + /** * Returns an {@code Observable} that emits the items in a specified {@link ObservableSource} before it begins to emit * items emitted by the current {@code Observable}. diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 5e9b084ad2..5911000d28 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -20,6 +20,7 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; +import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; @@ -4286,6 +4287,129 @@ public final Single retryWhen(@NonNull Function, return toSingle(toFlowable().retryWhen(handler)); } + /** + * Returns a {@link Flowable} which first runs the other {@link CompletableSource} + * then the current {@code Single} if the other completed normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code CompletableSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull CompletableSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Completable.wrap(other).toFlowable(), toFlowable()); + } + + /** + * Returns a {@link Flowable} which first runs the other {@link SingleSource} + * then the current {@code Single} if the other succeeded normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code SingleSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull SingleSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Single.wrap(other).toFlowable(), toFlowable()); + } + + /** + * Returns a {@link Flowable} which first runs the other {@link MaybeSource} + * then the current {@code Single} if the other succeeded or completed normally. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code MaybeSource} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + @BackpressureSupport(BackpressureKind.FULL) + public final Flowable startWith(@NonNull MaybeSource other) { + Objects.requireNonNull(other, "other is null"); + return Flowable.concat(Maybe.wrap(other).toFlowable(), toFlowable()); + } + + /** + * Returns an {@link Observable} which first delivers the events + * of the other {@link ObservableSource} then runs the current {@code Single}. + *

+ * + *

+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code ObservableSource} to run first + * @return the new {@code Observable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Observable startWith(@NonNull ObservableSource other) { + Objects.requireNonNull(other, "other is null"); + return Observable.wrap(other).concatWith(this.toObservable()); + } + + /** + * Returns a {@link Flowable} which first delivers the events + * of the other {@link Publisher} then runs the current {@code Single}. + *

+ * + *

+ *
Backpressure:
+ *
The returned {@code Flowable} honors the backpressure of the downstream consumer + * and expects the other {@code Publisher} to honor it as well.
+ *
Scheduler:
+ *
{@code startWith} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param other the other {@code Publisher} to run first + * @return the new {@code Flowable} instance + * @throws NullPointerException if {@code other} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.FULL) + @SchedulerSupport(SchedulerSupport.NONE) + public final Flowable startWith(@NonNull Publisher other) { + Objects.requireNonNull(other, "other is null"); + return toFlowable().startWith(other); + } + /** * Subscribes to a {@code Single} but ignore its emission or notification. *

diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableStartWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableStartWithTest.java new file mode 100644 index 0000000000..065a600a0e --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableStartWithTest.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.completable; + +import static org.mockito.Mockito.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class CompletableStartWithTest { + + @Test + public void singleNormal() { + Completable.complete().startWith(Single.just(1)) + .test() + .assertResult(1); + } + + @Test + public void singleError() { + Runnable run = mock(Runnable.class); + + Completable.fromRunnable(run).startWith(Single.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void maybeNormal() { + Completable.complete().startWith(Maybe.just(1)) + .test() + .assertResult(1); + } + + @Test + public void maybeEmptyNormal() { + Completable.complete().startWith(Maybe.empty()) + .test() + .assertResult(); + } + + @Test + public void maybeError() { + Runnable run = mock(Runnable.class); + + Completable.fromRunnable(run).startWith(Maybe.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableStartWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableStartWithTest.java new file mode 100644 index 0000000000..68f4ee6272 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableStartWithTest.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import static org.mockito.Mockito.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class FlowableStartWithTest { + + @Test + public void justCompletableComplete() { + Flowable.just(1).startWith(Completable.complete()) + .test() + .assertResult(1); + } + + @Test + public void emptyCompletableComplete() { + Flowable.empty().startWith(Completable.complete()) + .test() + .assertResult(); + } + + @Test + public void runCompletableError() { + Runnable run = mock(Runnable.class); + + Flowable.fromRunnable(run).startWith(Completable.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void justSingleJust() { + Flowable.just(1).startWith(Single.just(2)) + .test() + .assertResult(2, 1); + } + + @Test + public void emptySingleJust() { + Runnable run = mock(Runnable.class); + + Flowable.fromRunnable(run) + .startWith(Single.just(2)) + .test() + .assertResult(2); + + verify(run).run(); + } + + @Test + public void runSingleError() { + Runnable run = mock(Runnable.class); + + Flowable.fromRunnable(run).startWith(Single.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void justMaybeJust() { + Flowable.just(1).startWith(Maybe.just(2)) + .test() + .assertResult(2, 1); + } + + @Test + public void emptyMaybeJust() { + Runnable run = mock(Runnable.class); + + Flowable.fromRunnable(run) + .startWith(Maybe.just(2)) + .test() + .assertResult(2); + + verify(run).run(); + } + + @Test + public void runMaybeError() { + Runnable run = mock(Runnable.class); + + Flowable.fromRunnable(run).startWith(Maybe.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void justFlowableJust() { + Flowable.just(1).startWith(Flowable.just(2, 3, 4, 5)) + .test() + .assertResult(2, 3, 4, 5, 1); + } + + @Test + public void emptyFlowableJust() { + Runnable run = mock(Runnable.class); + + Flowable.fromRunnable(run) + .startWith(Flowable.just(2, 3, 4, 5)) + .test() + .assertResult(2, 3, 4, 5); + + verify(run).run(); + } + + @Test + public void emptyFlowableEmpty() { + Runnable run = mock(Runnable.class); + Runnable run2 = mock(Runnable.class); + + Flowable.fromRunnable(run) + .startWith(Flowable.fromRunnable(run2)) + .test() + .assertResult(); + + verify(run).run(); + verify(run2).run(); + } + + @Test + public void runFlowableError() { + Runnable run = mock(Runnable.class); + + Flowable.fromRunnable(run).startWith(Flowable.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeStartWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeStartWithTest.java new file mode 100644 index 0000000000..87969974d4 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeStartWithTest.java @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import static org.mockito.Mockito.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class MaybeStartWithTest { + + @Test + public void justCompletableComplete() { + Maybe.just(1).startWith(Completable.complete()) + .test() + .assertResult(1); + } + + @Test + public void emptyCompletableComplete() { + Maybe.empty().startWith(Completable.complete()) + .test() + .assertResult(); + } + + @Test + public void runCompletableError() { + Runnable run = mock(Runnable.class); + + Maybe.fromRunnable(run).startWith(Completable.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void justSingleJust() { + Maybe.just(1).startWith(Single.just(2)) + .test() + .assertResult(2, 1); + } + + @Test + public void emptySingleJust() { + Runnable run = mock(Runnable.class); + + Maybe.fromRunnable(run) + .startWith(Single.just(2)) + .test() + .assertResult(2); + + verify(run).run(); + } + + @Test + public void runSingleError() { + Runnable run = mock(Runnable.class); + + Maybe.fromRunnable(run).startWith(Single.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void justMaybeJust() { + Maybe.just(1).startWith(Maybe.just(2)) + .test() + .assertResult(2, 1); + } + + @Test + public void emptyMaybeJust() { + Runnable run = mock(Runnable.class); + + Maybe.fromRunnable(run) + .startWith(Maybe.just(2)) + .test() + .assertResult(2); + + verify(run).run(); + } + + @Test + public void runMaybeError() { + Runnable run = mock(Runnable.class); + + Maybe.fromRunnable(run).startWith(Maybe.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void justObservableJust() { + Maybe.just(1).startWith(Observable.just(2, 3, 4, 5)) + .test() + .assertResult(2, 3, 4, 5, 1); + } + + @Test + public void emptyObservableJust() { + Runnable run = mock(Runnable.class); + + Maybe.fromRunnable(run) + .startWith(Observable.just(2, 3, 4, 5)) + .test() + .assertResult(2, 3, 4, 5); + + verify(run).run(); + } + + @Test + public void emptyObservableEmpty() { + Runnable run = mock(Runnable.class); + Runnable run2 = mock(Runnable.class); + + Maybe.fromRunnable(run) + .startWith(Observable.fromRunnable(run2)) + .test() + .assertResult(); + + verify(run).run(); + verify(run2).run(); + } + + @Test + public void runObservableError() { + Runnable run = mock(Runnable.class); + + Maybe.fromRunnable(run).startWith(Observable.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void justFlowableJust() { + Maybe.just(1).startWith(Flowable.just(2, 3, 4, 5)) + .test() + .assertResult(2, 3, 4, 5, 1); + } + + @Test + public void emptyFlowableJust() { + Runnable run = mock(Runnable.class); + + Maybe.fromRunnable(run) + .startWith(Flowable.just(2, 3, 4, 5)) + .test() + .assertResult(2, 3, 4, 5); + + verify(run).run(); + } + + @Test + public void emptyFlowableEmpty() { + Runnable run = mock(Runnable.class); + Runnable run2 = mock(Runnable.class); + + Maybe.fromRunnable(run) + .startWith(Flowable.fromRunnable(run2)) + .test() + .assertResult(); + + verify(run).run(); + verify(run2).run(); + } + + @Test + public void runFlowableError() { + Runnable run = mock(Runnable.class); + + Maybe.fromRunnable(run).startWith(Flowable.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableStartWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableStartWithTest.java new file mode 100644 index 0000000000..47cf4dc962 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableStartWithTest.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.observable; + +import static org.mockito.Mockito.*; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class ObservableStartWithTest { + + @Test + public void justCompletableComplete() { + Observable.just(1).startWith(Completable.complete()) + .test() + .assertResult(1); + } + + @Test + public void emptyCompletableComplete() { + Observable.empty().startWith(Completable.complete()) + .test() + .assertResult(); + } + + @Test + public void runCompletableError() { + Runnable run = mock(Runnable.class); + + Observable.fromRunnable(run).startWith(Completable.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void justSingleJust() { + Observable.just(1).startWith(Single.just(2)) + .test() + .assertResult(2, 1); + } + + @Test + public void emptySingleJust() { + Runnable run = mock(Runnable.class); + + Observable.fromRunnable(run) + .startWith(Single.just(2)) + .test() + .assertResult(2); + + verify(run).run(); + } + + @Test + public void runSingleError() { + Runnable run = mock(Runnable.class); + + Observable.fromRunnable(run).startWith(Single.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void justMaybeJust() { + Observable.just(1).startWith(Maybe.just(2)) + .test() + .assertResult(2, 1); + } + + @Test + public void emptyMaybeJust() { + Runnable run = mock(Runnable.class); + + Observable.fromRunnable(run) + .startWith(Maybe.just(2)) + .test() + .assertResult(2); + + verify(run).run(); + } + + @Test + public void runMaybeError() { + Runnable run = mock(Runnable.class); + + Observable.fromRunnable(run).startWith(Maybe.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } + + @Test + public void justObservableJust() { + Observable.just(1).startWith(Observable.just(2, 3, 4, 5)) + .test() + .assertResult(2, 3, 4, 5, 1); + } + + @Test + public void emptyObservableJust() { + Runnable run = mock(Runnable.class); + + Observable.fromRunnable(run) + .startWith(Observable.just(2, 3, 4, 5)) + .test() + .assertResult(2, 3, 4, 5); + + verify(run).run(); + } + + @Test + public void emptyObservableEmpty() { + Runnable run = mock(Runnable.class); + Runnable run2 = mock(Runnable.class); + + Observable.fromRunnable(run) + .startWith(Observable.fromRunnable(run2)) + .test() + .assertResult(); + + verify(run).run(); + verify(run2).run(); + } + + @Test + public void runObservableError() { + Runnable run = mock(Runnable.class); + + Observable.fromRunnable(run).startWith(Observable.error(new TestException())) + .test() + .assertFailure(TestException.class); + + verify(run, never()).run(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleStartWithTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleStartWithTest.java new file mode 100644 index 0000000000..a3f7e7225a --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleStartWithTest.java @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class SingleStartWithTest { + + @Test + public void justCompletableComplete() { + Single.just(1) + .startWith(Completable.complete()) + .test() + .assertResult(1); + } + + @Test + public void justCompletableError() { + Single.just(1) + .startWith(Completable.error(new TestException())) + .test() + .assertFailure(TestException.class); + } + + @Test + public void justSingleJust() { + Single.just(1) + .startWith(Single.just(0)) + .test() + .assertResult(0, 1); + } + + @Test + public void justSingleError() { + Single.just(1) + .startWith(Single.error(new TestException())) + .test() + .assertFailure(TestException.class); + } + + @Test + public void justMaybeJust() { + Single.just(1) + .startWith(Maybe.just(0)) + .test() + .assertResult(0, 1); + } + + @Test + public void justMaybeEmpty() { + Single.just(1) + .startWith(Maybe.empty()) + .test() + .assertResult(1); + } + + @Test + public void justMaybeError() { + Single.just(1) + .startWith(Maybe.error(new TestException())) + .test() + .assertFailure(TestException.class); + } + + @Test + public void justObservableJust() { + Single.just(1) + .startWith(Observable.just(-1, 0)) + .test() + .assertResult(-1, 0, 1); + } + + @Test + public void justObservableEmpty() { + Single.just(1) + .startWith(Observable.empty()) + .test() + .assertResult(1); + } + + @Test + public void justObservableError() { + Single.just(1) + .startWith(Observable.error(new TestException())) + .test() + .assertFailure(TestException.class); + } + + @Test + public void justFlowableJust() { + Single.just(1) + .startWith(Flowable.just(-1, 0)) + .test() + .assertResult(-1, 0, 1); + } + + @Test + public void justFlowableEmpty() { + Single.just(1) + .startWith(Observable.empty()) + .test() + .assertResult(1); + } + + @Test + public void justFlowableError() { + Single.just(1) + .startWith(Flowable.error(new TestException())) + .test() + .assertFailure(TestException.class); + } +} From e077ed832678f5efeb15748d2a4aa4aafd29ef5a Mon Sep 17 00:00:00 2001 From: David Karnok Date: Tue, 28 Jan 2020 10:51:11 +0100 Subject: [PATCH 29/37] 3.x: Add Completable.onErrorReturn[Item] (#6886) --- .../reactivex/rxjava3/core/Completable.java | 58 +++++++++++ .../java/io/reactivex/rxjava3/core/Maybe.java | 6 +- .../completable/CompletableOnErrorReturn.java | 99 +++++++++++++++++++ .../operators/maybe/MaybeOnErrorReturn.java | 14 +-- .../completable/CompletableOnErrorXTest.java | 57 +++++++++++ 5 files changed, 224 insertions(+), 10 deletions(-) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorReturn.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 2ab23028bd..7e28439ae2 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -2323,6 +2323,64 @@ public final Completable onErrorResumeWith(@NonNull CompletableSource fallback) return onErrorResumeNext(Functions.justFunction(fallback)); } + /** + * Ends the flow with a success item returned by a function for the {@link Throwable} error signaled by the current + * {@code Completable} instead of signaling the error via {@code onError}. + *

+ * + *

+ * You can use this to prevent errors from propagating or to supply fallback data should errors be + * encountered. + *

+ *
Scheduler:
+ *
{@code onErrorReturn} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the item type to return on error + * @param itemSupplier + * a function that returns a single value that will be emitted as success value + * the current {@code Completable} signals an {@code onError} event + * @return the new {@link Maybe} instance + * @throws NullPointerException if {@code itemSupplier} is {@code null} + * @see ReactiveX operators documentation: Catch + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Maybe onErrorReturn(@NonNull Function itemSupplier) { + Objects.requireNonNull(itemSupplier, "itemSupplier is null"); + return RxJavaPlugins.onAssembly(new CompletableOnErrorReturn<>(this, itemSupplier)); + } + + /** + * Ends the flow with the given success item when the current {@code Completable} + * fails instead of signaling the error via {@code onError}. + *

+ * + *

+ * You can use this to prevent errors from propagating or to supply fallback data should errors be + * encountered. + *

+ *
Scheduler:
+ *
{@code onErrorReturnItem} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param the item type to return on error + * @param item + * the value that is emitted as {@code onSuccess} in case the current {@code Completable} signals an {@code onError} + * @return the new {@link Maybe} instance + * @throws NullPointerException if {@code item} is {@code null} + * @see ReactiveX operators documentation: Catch + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Maybe onErrorReturnItem(@NonNull T item) { + Objects.requireNonNull(item, "item is null"); + return onErrorReturn(Functions.justFunction(item)); + } + /** * Nulls out references to the upstream producer and downstream {@link CompletableObserver} if * the sequence is terminated or downstream calls {@code dispose()}. diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 96ff14c1e9..40902efa53 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -4467,7 +4467,7 @@ public final Maybe onErrorResumeNext(@NonNull Function - * + * *

* You can use this to prevent errors from propagating or to supply fallback data should errors be * encountered. @@ -4494,7 +4494,7 @@ public final Maybe onErrorReturn(@NonNull Function - * + * *

* You can use this to prevent errors from propagating or to supply fallback data should errors be * encountered. @@ -4504,7 +4504,7 @@ public final Maybe onErrorReturn(@NonNull Function * * @param item - * the value that is emitted as {@code onSuccess} in case this {@code Maybe} signals an {@code onError} + * the value that is emitted as {@code onSuccess} in case the current {@code Maybe} signals an {@code onError} * @return the new {@code Maybe} instance * @throws NullPointerException if {@code item} is {@code null} * @see ReactiveX operators documentation: Catch diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorReturn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorReturn.java new file mode 100644 index 0000000000..c8fa43499f --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorReturn.java @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.completable; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; + +import java.util.Objects; + +/** + * Returns a value generated via a function if the main source signals an onError. + * @param the value type + * @since 3.0.0 + */ +public final class CompletableOnErrorReturn extends Maybe { + + final CompletableSource source; + + final Function valueSupplier; + + public CompletableOnErrorReturn(CompletableSource source, + Function valueSupplier) { + this.source = source; + this.valueSupplier = valueSupplier; + } + + @Override + protected void subscribeActual(MaybeObserver observer) { + source.subscribe(new OnErrorReturnMaybeObserver<>(observer, valueSupplier)); + } + + static final class OnErrorReturnMaybeObserver implements CompletableObserver, Disposable { + + final MaybeObserver downstream; + + final Function itemSupplier; + + Disposable upstream; + + OnErrorReturnMaybeObserver(MaybeObserver actual, + Function itemSupplier) { + this.downstream = actual; + this.itemSupplier = itemSupplier; + } + + @Override + public void dispose() { + upstream.dispose(); + } + + @Override + public boolean isDisposed() { + return upstream.isDisposed(); + } + + @Override + public void onSubscribe(Disposable d) { + if (DisposableHelper.validate(this.upstream, d)) { + this.upstream = d; + + downstream.onSubscribe(this); + } + } + + @Override + public void onError(Throwable e) { + T v; + + try { + v = Objects.requireNonNull(itemSupplier.apply(e), "The itemSupplier returned a null value"); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + downstream.onError(new CompositeException(e, ex)); + return; + } + + downstream.onSuccess(v); + } + + @Override + public void onComplete() { + downstream.onComplete(); + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorReturn.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorReturn.java index 1a75120e84..190856d5c7 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorReturn.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeOnErrorReturn.java @@ -27,31 +27,31 @@ */ public final class MaybeOnErrorReturn extends AbstractMaybeWithUpstream { - final Function valueSupplier; + final Function itemSupplier; public MaybeOnErrorReturn(MaybeSource source, - Function valueSupplier) { + Function itemSupplier) { super(source); - this.valueSupplier = valueSupplier; + this.itemSupplier = itemSupplier; } @Override protected void subscribeActual(MaybeObserver observer) { - source.subscribe(new OnErrorReturnMaybeObserver<>(observer, valueSupplier)); + source.subscribe(new OnErrorReturnMaybeObserver<>(observer, itemSupplier)); } static final class OnErrorReturnMaybeObserver implements MaybeObserver, Disposable { final MaybeObserver downstream; - final Function valueSupplier; + final Function itemSupplier; Disposable upstream; OnErrorReturnMaybeObserver(MaybeObserver actual, Function valueSupplier) { this.downstream = actual; - this.valueSupplier = valueSupplier; + this.itemSupplier = valueSupplier; } @Override @@ -83,7 +83,7 @@ public void onError(Throwable e) { T v; try { - v = Objects.requireNonNull(valueSupplier.apply(e), "The valueSupplier returned a null value"); + v = Objects.requireNonNull(itemSupplier.apply(e), "The itemSupplier returned a null value"); } catch (Throwable ex) { Exceptions.throwIfFatal(ex); downstream.onError(new CompositeException(e, ex)); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorXTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorXTest.java index 4a1333b530..531f13b8cc 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorXTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableOnErrorXTest.java @@ -15,10 +15,16 @@ import static org.junit.Assert.assertEquals; +import java.io.IOException; + import org.junit.Test; import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.subjects.CompletableSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; public class CompletableOnErrorXTest extends RxJavaTest { @@ -46,4 +52,55 @@ public CompletableSource apply(Throwable e) throws Exception { assertEquals(0, call[0]); } + + @Test + public void onErrorReturnConst() { + Completable.error(new TestException()) + .onErrorReturnItem(1) + .test() + .assertResult(1); + } + + @Test + public void onErrorReturn() { + Completable.error(new TestException()) + .onErrorReturn(Functions.justFunction(1)) + .test() + .assertResult(1); + } + + @Test + public void onErrorReturnFunctionThrows() { + TestHelper.assertCompositeExceptions(Completable.error(new TestException()) + .onErrorReturn(new Function() { + @Override + public Object apply(Throwable v) throws Exception { + throw new IOException(); + } + }) + .to(TestHelper.testConsumer()), TestException.class, IOException.class); + } + + @Test + public void onErrorReturnEmpty() { + Completable.complete() + .onErrorReturnItem(2) + .test() + .assertResult(); + } + + @Test + public void onErrorReturnDispose() { + TestHelper.checkDisposed(CompletableSubject.create().onErrorReturnItem(1)); + } + + @Test + public void onErrorReturnDoubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeCompletableToMaybe(new Function>() { + @Override + public MaybeSource apply(Completable v) throws Exception { + return v.onErrorReturnItem(1); + } + }); + } } From 2d8660e070fe65b8089855ba1a58ef49d7c1b70a Mon Sep 17 00:00:00 2001 From: David Karnok Date: Tue, 28 Jan 2020 12:06:37 +0100 Subject: [PATCH 30/37] 3.x: Add safeSubscribe to Maybe, Single & Completable (#6887) --- docs/Operator-Matrix.md | 27 +-- .../reactivex/rxjava3/core/Completable.java | 25 +++ .../java/io/reactivex/rxjava3/core/Maybe.java | 25 +++ .../io/reactivex/rxjava3/core/Single.java | 25 +++ .../observers/SafeCompletableObserver.java | 78 +++++++ .../internal/observers/SafeMaybeObserver.java | 91 ++++++++ .../observers/SafeSingleObserver.java | 79 +++++++ .../CompletableSafeSubscribeTest.java | 148 +++++++++++++ .../maybe/MaybeSafeSubscribeTest.java | 197 ++++++++++++++++++ .../single/SingleSafeSubscribeTest.java | 154 ++++++++++++++ .../util/OperatorMatrixGenerator.java | 7 +- 11 files changed, 837 insertions(+), 19 deletions(-) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/observers/SafeCompletableObserver.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/observers/SafeMaybeObserver.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/observers/SafeSingleObserver.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSafeSubscribeTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSafeSubscribeTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSafeSubscribeTest.java diff --git a/docs/Operator-Matrix.md b/docs/Operator-Matrix.md index 2ddd1cf21f..dfa16162e7 100644 --- a/docs/Operator-Matrix.md +++ b/docs/Operator-Matrix.md @@ -138,8 +138,8 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `mapOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| `materialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `merge`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`mergeArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`mergeArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`mergeArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`mergeArrayDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `mergeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `mergeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `never`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -151,8 +151,8 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `onErrorComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `onErrorResumeNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `onErrorResumeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`onErrorReturn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| -`onErrorReturnItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`onErrorReturn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`onErrorReturnItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `onTerminateDetach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `parallel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([86](#notes-86))| `publish`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| @@ -168,11 +168,11 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `retry`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `retryUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `retryWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`safeSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`safeSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| `scan`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))| `scanWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))| -`sequenceEqual`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)| +`sequenceEqual`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `serialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))| `share`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| `single`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| @@ -185,7 +185,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `skipUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))| `skipWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| `sorted`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))| -`startWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_half.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`startWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `startWithArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([96](#notes-96))| `startWithItem`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([97](#notes-97))| `startWithIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([98](#notes-98))| @@ -237,7 +237,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([111](#notes-111))| `zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([112](#notes-112))| `zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([113](#notes-113))| -**237 operators** | **215** | **209** | **116** | **103** | **80** | +**237 operators** | **215** | **209** | **118** | **107** | **84** | #### Notes 1 Use [`contains()`](#contains).
@@ -356,13 +356,4 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat #### Under development -1. Single.mergeArray() -2. Single.mergeArrayDelayError() -3. Completable.onErrorReturn() -4. Completable.onErrorReturnItem() -5. Maybe.safeSubscribe() -6. Single.safeSubscribe() -7. Completable.safeSubscribe() -8. Completable.sequenceEqual() -9. Maybe.startWith() -10. Single.startWith() +*Currently, all intended operators are implemented.* diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 7e28439ae2..83e7848a51 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -2651,6 +2651,31 @@ public final Completable retryWhen(@NonNull Function return fromPublisher(toFlowable().retryWhen(handler)); } + /** + * Wraps the given {@link CompletableObserver}, catches any {@link RuntimeException}s thrown by its + * {@link CompletableObserver#onSubscribe(Disposable)}, {@link CompletableObserver#onError(Throwable)} + * or {@link CompletableObserver#onComplete()} methods and routes those to the global + * error handler via {@link RxJavaPlugins#onError(Throwable)}. + *

+ * By default, the {@code Completable} protocol forbids the {@code onXXX} methods to throw, but some + * {@code CompletableObserver} implementation may do it anyway, causing undefined behavior in the + * upstream. This method and the underlying safe wrapper ensures such misbehaving consumers don't + * disrupt the protocol. + *

+ *
Scheduler:
+ *
{@code safeSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param observer the potentially misbehaving {@code CompletableObserver} + * @throws NullPointerException if {@code observer} is {@code null} + * @see #subscribe(Action, Consumer) + * @since 3.0.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void safeSubscribe(@NonNull CompletableObserver observer) { + Objects.requireNonNull(observer, "observer is null"); + subscribe(new SafeCompletableObserver(observer)); + } + /** * Returns a {@code Completable} which first runs the other {@link CompletableSource} * then the current {@code Completable} if the other completed normally. diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 40902efa53..ba42452513 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -4860,6 +4860,31 @@ public final Maybe retryWhen( return toFlowable().retryWhen(handler).singleElement(); } + /** + * Wraps the given {@link MaybeObserver}, catches any {@link RuntimeException}s thrown by its + * {@link MaybeObserver#onSubscribe(Disposable)}, {@link MaybeObserver#onSuccess(Object)}, + * {@link MaybeObserver#onError(Throwable)} or {@link MaybeObserver#onComplete()} methods + * and routes those to the global error handler via {@link RxJavaPlugins#onError(Throwable)}. + *

+ * By default, the {@code Maybe} protocol forbids the {@code onXXX} methods to throw, but some + * {@code MaybeObserver} implementation may do it anyway, causing undefined behavior in the + * upstream. This method and the underlying safe wrapper ensures such misbehaving consumers don't + * disrupt the protocol. + *

+ *
Scheduler:
+ *
{@code safeSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param observer the potentially misbehaving {@code MaybeObserver} + * @throws NullPointerException if {@code observer} is {@code null} + * @see #subscribe(Consumer,Consumer, Action) + * @since 3.0.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void safeSubscribe(@NonNull MaybeObserver observer) { + Objects.requireNonNull(observer, "observer is null"); + subscribe(new SafeMaybeObserver<>(observer)); + } + /** * Returns a {@link Flowable} which first runs the other {@link CompletableSource} * then the current {@code Maybe} if the other completed normally. diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 5911000d28..12431fedb6 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -4287,6 +4287,31 @@ public final Single retryWhen(@NonNull Function, return toSingle(toFlowable().retryWhen(handler)); } + /** + * Wraps the given {@link SingleObserver}, catches any {@link RuntimeException}s thrown by its + * {@link SingleObserver#onSubscribe(Disposable)}, {@link SingleObserver#onSuccess(Object)} or + * {@link SingleObserver#onError(Throwable)} methods* and routes those to the global error handler + * via {@link RxJavaPlugins#onError(Throwable)}. + *

+ * By default, the {@code Single} protocol forbids the {@code onXXX} methods to throw, but some + * {@code SingleObserver} implementation may do it anyway, causing undefined behavior in the + * upstream. This method and the underlying safe wrapper ensures such misbehaving consumers don't + * disrupt the protocol. + *

+ *
Scheduler:
+ *
{@code safeSubscribe} does not operate by default on a particular {@link Scheduler}.
+ *
+ * @param observer the potentially misbehaving {@code SingleObserver} + * @throws NullPointerException if {@code observer} is {@code null} + * @see #subscribe(Consumer,Consumer) + * @since 3.0.0 + */ + @SchedulerSupport(SchedulerSupport.NONE) + public final void safeSubscribe(@NonNull SingleObserver observer) { + Objects.requireNonNull(observer, "observer is null"); + subscribe(new SafeSingleObserver<>(observer)); + } + /** * Returns a {@link Flowable} which first runs the other {@link CompletableSource} * then the current {@code Single} if the other completed normally. diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/SafeCompletableObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeCompletableObserver.java new file mode 100644 index 0000000000..d9e929c234 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeCompletableObserver.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.CompletableObserver; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Wraps another {@link CompletableObserver} and catches exceptions thrown by its + * {@code onSubscribe}, {@code onError} or + * {@code onComplete} methods despite the protocol forbids it. + *

+ * Such exceptions are routed to the {@link RxJavaPlugins#onError(Throwable)} handler. + * + * @since 3.0.0 + */ +public final class SafeCompletableObserver implements CompletableObserver { + + final CompletableObserver downstream; + + boolean onSubscribeFailed; + + public SafeCompletableObserver(CompletableObserver downstream) { + this.downstream = downstream; + } + + @Override + public void onSubscribe(@NonNull Disposable d) { + try { + downstream.onSubscribe(d); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + onSubscribeFailed = true; + d.dispose(); + RxJavaPlugins.onError(ex); + } + } + + @Override + public void onError(@NonNull Throwable e) { + if (onSubscribeFailed) { + RxJavaPlugins.onError(e); + } else { + try { + downstream.onError(e); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + RxJavaPlugins.onError(new CompositeException(e, ex)); + } + } + } + + @Override + public void onComplete() { + if (!onSubscribeFailed) { + try { + downstream.onComplete(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + RxJavaPlugins.onError(ex); + } + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/SafeMaybeObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeMaybeObserver.java new file mode 100644 index 0000000000..a6e794b1fd --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeMaybeObserver.java @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.MaybeObserver; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Wraps another {@link MaybeObserver} and catches exceptions thrown by its + * {@code onSubscribe}, {@code onSuccess}, {@code onError} or + * {@code onComplete} methods despite the protocol forbids it. + *

+ * Such exceptions are routed to the {@link RxJavaPlugins#onError(Throwable)} handler. + * + * @param the element type of the sequence + * @since 3.0.0 + */ +public final class SafeMaybeObserver implements MaybeObserver { + + final MaybeObserver downstream; + + boolean onSubscribeFailed; + + public SafeMaybeObserver(MaybeObserver downstream) { + this.downstream = downstream; + } + + @Override + public void onSubscribe(@NonNull Disposable d) { + try { + downstream.onSubscribe(d); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + onSubscribeFailed = true; + d.dispose(); + RxJavaPlugins.onError(ex); + } + } + + @Override + public void onSuccess(@NonNull T t) { + if (!onSubscribeFailed) { + try { + downstream.onSuccess(t); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + RxJavaPlugins.onError(ex); + } + } + } + + @Override + public void onError(@NonNull Throwable e) { + if (onSubscribeFailed) { + RxJavaPlugins.onError(e); + } else { + try { + downstream.onError(e); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + RxJavaPlugins.onError(new CompositeException(e, ex)); + } + } + } + + @Override + public void onComplete() { + if (!onSubscribeFailed) { + try { + downstream.onComplete(); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + RxJavaPlugins.onError(ex); + } + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/observers/SafeSingleObserver.java b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeSingleObserver.java new file mode 100644 index 0000000000..6757350756 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/observers/SafeSingleObserver.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.observers; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.SingleObserver; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.plugins.RxJavaPlugins; + +/** + * Wraps another {@link SingleObserver} and catches exceptions thrown by its + * {@code onSubscribe}, {@code onSuccess} or {@code onError} methods despite + * the protocol forbids it. + *

+ * Such exceptions are routed to the {@link RxJavaPlugins#onError(Throwable)} handler. + * + * @param the element type of the sequence + * @since 3.0.0 + */ +public final class SafeSingleObserver implements SingleObserver { + + final SingleObserver downstream; + + boolean onSubscribeFailed; + + public SafeSingleObserver(SingleObserver downstream) { + this.downstream = downstream; + } + + @Override + public void onSubscribe(@NonNull Disposable d) { + try { + downstream.onSubscribe(d); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + onSubscribeFailed = true; + d.dispose(); + RxJavaPlugins.onError(ex); + } + } + + @Override + public void onSuccess(@NonNull T t) { + if (!onSubscribeFailed) { + try { + downstream.onSuccess(t); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + RxJavaPlugins.onError(ex); + } + } + } + + @Override + public void onError(@NonNull Throwable e) { + if (onSubscribeFailed) { + RxJavaPlugins.onError(e); + } else { + try { + downstream.onError(e); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + RxJavaPlugins.onError(new CompositeException(e, ex)); + } + } + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSafeSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSafeSubscribeTest.java new file mode 100644 index 0000000000..234fb0290c --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableSafeSubscribeTest.java @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.completable; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import java.io.IOException; + +import org.junit.Test; +import org.mockito.InOrder; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class CompletableSafeSubscribeTest { + + @Test + public void normalError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + CompletableObserver consumer = mock(CompletableObserver.class); + + Completable.error(new TestException()) + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onError(any(TestException.class)); + order.verifyNoMoreInteractions(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void normalEmpty() throws Throwable { + TestHelper.withErrorTracking(errors -> { + CompletableObserver consumer = mock(CompletableObserver.class); + + Completable.complete() + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onComplete(); + order.verifyNoMoreInteractions(); + }); + } + + @Test + public void onSubscribeCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + CompletableObserver consumer = mock(CompletableObserver.class); + doThrow(new TestException()).when(consumer).onSubscribe(any()); + + Disposable d = Disposable.empty(); + + new Completable() { + @Override + protected void subscribeActual(@NonNull CompletableObserver observer) { + observer.onSubscribe(d); + // none of the following should arrive at the consumer + observer.onError(new IOException()); + observer.onComplete(); + } + } + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verifyNoMoreInteractions(); + + assertTrue(d.isDisposed()); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + TestHelper.assertUndeliverable(errors, 1, IOException.class); + }); + } + + @Test + public void onErrorCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + CompletableObserver consumer = mock(CompletableObserver.class); + doThrow(new TestException()).when(consumer).onError(any()); + + new Completable() { + @Override + protected void subscribeActual(@NonNull CompletableObserver observer) { + observer.onSubscribe(Disposable.empty()); + // none of the following should arrive at the consumer + observer.onError(new IOException()); + } + } + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onError(any(IOException.class)); + order.verifyNoMoreInteractions(); + + TestHelper.assertError(errors, 0, CompositeException.class); + + CompositeException compositeException = (CompositeException)errors.get(0); + TestHelper.assertError(compositeException.getExceptions(), 0, IOException.class); + TestHelper.assertError(compositeException.getExceptions(), 1, TestException.class); + }); + } + + @Test + public void onCompleteCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + CompletableObserver consumer = mock(CompletableObserver.class); + doThrow(new TestException()).when(consumer).onComplete(); + + new Completable() { + @Override + protected void subscribeActual(@NonNull CompletableObserver observer) { + observer.onSubscribe(Disposable.empty()); + // none of the following should arrive at the consumer + observer.onComplete(); + } + } + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onComplete(); + order.verifyNoMoreInteractions(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSafeSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSafeSubscribeTest.java new file mode 100644 index 0000000000..5083c20f2c --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeSafeSubscribeTest.java @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import java.io.IOException; + +import org.junit.Test; +import org.mockito.InOrder; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class MaybeSafeSubscribeTest { + + @Test + public void normalSuccess() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + MaybeObserver consumer = mock(MaybeObserver.class); + + Maybe.just(1) + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onSuccess(1); + order.verifyNoMoreInteractions(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void normalError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + MaybeObserver consumer = mock(MaybeObserver.class); + + Maybe.error(new TestException()) + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onError(any(TestException.class)); + order.verifyNoMoreInteractions(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void normalEmpty() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + MaybeObserver consumer = mock(MaybeObserver.class); + + Maybe.empty() + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onComplete(); + order.verifyNoMoreInteractions(); + }); + } + + @Test + public void onSubscribeCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + MaybeObserver consumer = mock(MaybeObserver.class); + doThrow(new TestException()).when(consumer).onSubscribe(any()); + + Disposable d = Disposable.empty(); + + new Maybe() { + @Override + protected void subscribeActual(@NonNull MaybeObserver observer) { + observer.onSubscribe(d); + // none of the following should arrive at the consumer + observer.onSuccess(1); + observer.onError(new IOException()); + observer.onComplete(); + } + } + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verifyNoMoreInteractions(); + + assertTrue(d.isDisposed()); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + TestHelper.assertUndeliverable(errors, 1, IOException.class); + }); + } + + @Test + public void onSuccessCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + MaybeObserver consumer = mock(MaybeObserver.class); + doThrow(new TestException()).when(consumer).onSuccess(any()); + + new Maybe() { + @Override + protected void subscribeActual(@NonNull MaybeObserver observer) { + observer.onSubscribe(Disposable.empty()); + observer.onSuccess(1); + } + } + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onSuccess(1); + order.verifyNoMoreInteractions(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void onErrorCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + MaybeObserver consumer = mock(MaybeObserver.class); + doThrow(new TestException()).when(consumer).onError(any()); + + new Maybe() { + @Override + protected void subscribeActual(@NonNull MaybeObserver observer) { + observer.onSubscribe(Disposable.empty()); + // none of the following should arrive at the consumer + observer.onError(new IOException()); + } + } + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onError(any(IOException.class)); + order.verifyNoMoreInteractions(); + + TestHelper.assertError(errors, 0, CompositeException.class); + + CompositeException compositeException = (CompositeException)errors.get(0); + TestHelper.assertError(compositeException.getExceptions(), 0, IOException.class); + TestHelper.assertError(compositeException.getExceptions(), 1, TestException.class); + }); + } + + @Test + public void onCompleteCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + MaybeObserver consumer = mock(MaybeObserver.class); + doThrow(new TestException()).when(consumer).onComplete(); + + new Maybe() { + @Override + protected void subscribeActual(@NonNull MaybeObserver observer) { + observer.onSubscribe(Disposable.empty()); + // none of the following should arrive at the consumer + observer.onComplete(); + } + } + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onComplete(); + order.verifyNoMoreInteractions(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSafeSubscribeTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSafeSubscribeTest.java new file mode 100644 index 0000000000..80abb4cb1a --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleSafeSubscribeTest.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import java.io.IOException; + +import org.junit.Test; +import org.mockito.InOrder; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleSafeSubscribeTest { + + @Test + public void normalSuccess() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + SingleObserver consumer = mock(SingleObserver.class); + + Single.just(1) + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onSuccess(1); + order.verifyNoMoreInteractions(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void normalError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + SingleObserver consumer = mock(SingleObserver.class); + + Single.error(new TestException()) + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onError(any(TestException.class)); + order.verifyNoMoreInteractions(); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void onSubscribeCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + SingleObserver consumer = mock(SingleObserver.class); + doThrow(new TestException()).when(consumer).onSubscribe(any()); + + Disposable d = Disposable.empty(); + + new Single() { + @Override + protected void subscribeActual(@NonNull SingleObserver observer) { + observer.onSubscribe(d); + // none of the following should arrive at the consumer + observer.onSuccess(1); + observer.onError(new IOException()); + } + } + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verifyNoMoreInteractions(); + + assertTrue(d.isDisposed()); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + TestHelper.assertUndeliverable(errors, 1, IOException.class); + }); + } + + @Test + public void onSuccessCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + SingleObserver consumer = mock(SingleObserver.class); + doThrow(new TestException()).when(consumer).onSuccess(any()); + + new Single() { + @Override + protected void subscribeActual(@NonNull SingleObserver observer) { + observer.onSubscribe(Disposable.empty()); + observer.onSuccess(1); + } + } + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onSuccess(1); + order.verifyNoMoreInteractions(); + + TestHelper.assertUndeliverable(errors, 0, TestException.class); + }); + } + + @Test + public void onErrorCrash() throws Throwable { + TestHelper.withErrorTracking(errors -> { + @SuppressWarnings("unchecked") + SingleObserver consumer = mock(SingleObserver.class); + doThrow(new TestException()).when(consumer).onError(any()); + + new Single() { + @Override + protected void subscribeActual(@NonNull SingleObserver observer) { + observer.onSubscribe(Disposable.empty()); + // none of the following should arrive at the consumer + observer.onError(new IOException()); + } + } + .safeSubscribe(consumer); + + InOrder order = inOrder(consumer); + order.verify(consumer).onSubscribe(any(Disposable.class)); + order.verify(consumer).onError(any(IOException.class)); + order.verifyNoMoreInteractions(); + + TestHelper.assertError(errors, 0, CompositeException.class); + + CompositeException compositeException = (CompositeException)errors.get(0); + TestHelper.assertError(compositeException.getExceptions(), 0, IOException.class); + TestHelper.assertError(compositeException.getExceptions(), 1, TestException.class); + }); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java index 0e2c0ada16..714a6809f9 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/OperatorMatrixGenerator.java @@ -147,7 +147,12 @@ public static void main(String[] args) throws IOException { out.println("
"); } } - if (!tbdList.isEmpty()) { + if (tbdList.isEmpty()) { + out.println(); + out.println("#### Under development"); + out.println(); + out.println("*Currently, all intended operators are implemented.*"); + } else { out.println(); out.println("#### Under development"); out.println(); From 1ede60786a1a8f00f1fb3968d0701a323ed86f2f Mon Sep 17 00:00:00 2001 From: David Karnok Date: Tue, 28 Jan 2020 15:59:54 +0100 Subject: [PATCH 31/37] 3.x: Use more appropriate operators when delegating to Flowable ops (#6888) * 3.x: Use more appropriate operators when delegating to Flowable ops * Remove now-unused classes --- .../java/io/reactivex/rxjava3/core/Maybe.java | 20 ++----- .../io/reactivex/rxjava3/core/Single.java | 47 +++++++--------- ...ava => FlowableFlatMapMaybePublisher.java} | 32 ++++++----- .../FlowableFlatMapSinglePublisher.java | 49 +++++++++++++++++ .../FlowableConcatMapMaybePublisher.java} | 38 +++++++------ .../FlowableConcatMapSinglePublisher.java | 55 +++++++++++++++++++ .../mixed/ObservableConcatMapSingle.java | 4 +- .../single/SingleInternalHelper.java | 16 ------ .../single/SingleInternalHelperTest.java | 6 -- .../io/reactivex/rxjava3/maybe/MaybeTest.java | 2 - 10 files changed, 173 insertions(+), 96 deletions(-) rename src/main/java/io/reactivex/rxjava3/internal/operators/flowable/{FlowableFlatMapPublisher.java => FlowableFlatMapMaybePublisher.java} (53%) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSinglePublisher.java rename src/main/java/io/reactivex/rxjava3/internal/operators/{flowable/FlowableConcatMapPublisher.java => mixed/FlowableConcatMapMaybePublisher.java} (51%) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSinglePublisher.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index ba42452513..d4116406b4 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -344,11 +344,10 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Maybe @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - @SuppressWarnings({ "unchecked", "rawtypes" }) public static Flowable concat(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int prefetch) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); - return RxJavaPlugins.onAssembly(new FlowableConcatMapPublisher(sources, MaybeToPublisher.instance(), prefetch, ErrorMode.IMMEDIATE)); + return RxJavaPlugins.onAssembly(new FlowableConcatMapMaybePublisher<>(sources, Functions.identity(), ErrorMode.IMMEDIATE, prefetch)); } /** @@ -1141,7 +1140,7 @@ public static Maybe fromRunnable(@NonNull Runnable run) { @SchedulerSupport(SchedulerSupport.NONE) @NonNull public static Flowable merge(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { - return merge(Flowable.fromIterable(sources)); + return Flowable.fromIterable(sources).flatMapMaybe(Functions.identity(), false, Integer.MAX_VALUE); } /** @@ -1218,11 +1217,10 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends MaybeS @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - @SuppressWarnings({ "unchecked", "rawtypes" }) public static Flowable merge(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); - return RxJavaPlugins.onAssembly(new FlowableFlatMapPublisher(sources, MaybeToPublisher.instance(), false, maxConcurrency, 1)); + return RxJavaPlugins.onAssembly(new FlowableFlatMapMaybePublisher<>(sources, Functions.identity(), false, maxConcurrency)); } /** @@ -1490,7 +1488,6 @@ public static Flowable mergeArray(MaybeSource... sources) { * @throws NullPointerException if {@code sources} is {@code null} * @see ReactiveX operators documentation: Merge */ - @SuppressWarnings({ "unchecked", "rawtypes" }) @BackpressureSupport(BackpressureKind.FULL) @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -1498,10 +1495,7 @@ public static Flowable mergeArray(MaybeSource... sources) { @NonNull public static Flowable mergeArrayDelayError(@NonNull MaybeSource... sources) { Objects.requireNonNull(sources, "sources is null"); - if (sources.length == 0) { - return Flowable.empty(); - } - return Flowable.fromArray(sources).flatMap((Function)MaybeToPublisher.instance(), true, sources.length); + return Flowable.fromArray(sources).flatMapMaybe(Functions.identity(), true, Math.max(1, sources.length)); } /** @@ -1533,13 +1527,12 @@ public static Flowable mergeArrayDelayError(@NonNull MaybeSourceReactiveX operators documentation: Merge */ - @SuppressWarnings({ "unchecked", "rawtypes" }) @BackpressureSupport(BackpressureKind.FULL) @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { - return Flowable.fromIterable(sources).flatMap((Function)MaybeToPublisher.instance(), true); + return Flowable.fromIterable(sources).flatMapMaybe(Functions.identity(), true, Integer.MAX_VALUE); } /** @@ -1609,7 +1602,6 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte * @see ReactiveX operators documentation: Merge * @since 2.2 */ - @SuppressWarnings({ "unchecked", "rawtypes" }) @BackpressureSupport(BackpressureKind.FULL) @CheckReturnValue @NonNull @@ -1617,7 +1609,7 @@ public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? exte public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); - return RxJavaPlugins.onAssembly(new FlowableFlatMapPublisher(sources, MaybeToPublisher.instance(), true, maxConcurrency, 1)); + return RxJavaPlugins.onAssembly(new FlowableFlatMapMaybePublisher<>(sources, Functions.identity(), true, maxConcurrency)); } /** diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 12431fedb6..7db69e5bc5 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -20,7 +20,6 @@ import org.reactivestreams.*; import io.reactivex.rxjava3.annotations.*; -import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.*; import io.reactivex.rxjava3.functions.*; @@ -32,7 +31,7 @@ import io.reactivex.rxjava3.internal.operators.flowable.*; import io.reactivex.rxjava3.internal.operators.maybe.*; import io.reactivex.rxjava3.internal.operators.mixed.*; -import io.reactivex.rxjava3.internal.operators.observable.*; +import io.reactivex.rxjava3.internal.operators.observable.ObservableSingleSingle; import io.reactivex.rxjava3.internal.operators.single.*; import io.reactivex.rxjava3.internal.util.ErrorMode; import io.reactivex.rxjava3.observers.TestObserver; @@ -195,7 +194,7 @@ public static Single ambArray(@NonNull SingleSource... sourc @SchedulerSupport(SchedulerSupport.NONE) @BackpressureSupport(BackpressureKind.FULL) public static Flowable concat(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { - return concat(Flowable.fromIterable(sources)); + return Flowable.fromIterable(sources).concatMapSingleDelayError(Functions.identity(), false); } /** @@ -216,10 +215,9 @@ public static Flowable concat(@NonNull Iterable<@NonNull ? extends Single @CheckReturnValue @NonNull @SchedulerSupport(SchedulerSupport.NONE) - @SuppressWarnings({ "unchecked", "rawtypes" }) public static Observable concat(@NonNull ObservableSource> sources) { Objects.requireNonNull(sources, "sources is null"); - return RxJavaPlugins.onAssembly(new ObservableConcatMap(sources, SingleInternalHelper.toObservable(), 2, ErrorMode.IMMEDIATE)); + return RxJavaPlugins.onAssembly(new ObservableConcatMapSingle<>(sources, Functions.identity(), ErrorMode.IMMEDIATE, 2)); } /** @@ -272,11 +270,10 @@ public static Flowable concat(@NonNull Publisher<@NonNull ? extends Singl @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - @SuppressWarnings({ "unchecked", "rawtypes" }) public static Flowable concat(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int prefetch) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(prefetch, "prefetch"); - return RxJavaPlugins.onAssembly(new FlowableConcatMapPublisher(sources, SingleInternalHelper.toFlowable(), prefetch, ErrorMode.IMMEDIATE)); + return RxJavaPlugins.onAssembly(new FlowableConcatMapSinglePublisher<>(sources, Functions.identity(), ErrorMode.IMMEDIATE, prefetch)); } /** @@ -308,7 +305,7 @@ public static Flowable concat( ) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); - return concat(Flowable.fromArray(source1, source2)); + return Flowable.fromArray(source1, source2).concatMapSingleDelayError(Functions.identity(), false); } /** @@ -344,7 +341,7 @@ public static Flowable concat( Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); - return concat(Flowable.fromArray(source1, source2, source3)); + return Flowable.fromArray(source1, source2, source3).concatMapSingleDelayError(Functions.identity(), false); } /** @@ -383,7 +380,7 @@ public static Flowable concat( Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); Objects.requireNonNull(source4, "source4 is null"); - return concat(Flowable.fromArray(source1, source2, source3, source4)); + return Flowable.fromArray(source1, source2, source3, source4).concatMapSingleDelayError(Functions.identity(), false); } /** @@ -409,7 +406,7 @@ public static Flowable concat( @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs public static Flowable concatArray(@NonNull SingleSource... sources) { - return Flowable.fromArray(sources).concatMap(SingleInternalHelper.toFlowable(), 2); + return Flowable.fromArray(sources).concatMapSingleDelayError(Functions.identity(), false); } /** @@ -435,7 +432,7 @@ public static Flowable concatArray(@NonNull SingleSource... @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs public static Flowable concatArrayDelayError(@NonNull SingleSource... sources) { - return Flowable.fromArray(sources).concatMapDelayError(SingleInternalHelper.toFlowable(), true, 2); + return Flowable.fromArray(sources).concatMapSingleDelayError(Functions.identity(), true); } /** @@ -1091,7 +1088,7 @@ public static Single fromObservable(@NonNull ObservableSource Flowable merge(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { - return merge(Flowable.fromIterable(sources)); + return Flowable.fromIterable(sources).flatMapSingle(Functions.identity()); } /** @@ -1129,10 +1126,9 @@ public static Flowable merge(@NonNull Iterable<@NonNull ? extends SingleS @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - @SuppressWarnings({ "unchecked", "rawtypes" }) public static Flowable merge(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { Objects.requireNonNull(sources, "sources is null"); - return RxJavaPlugins.onAssembly(new FlowableFlatMapPublisher(sources, SingleInternalHelper.toFlowable(), false, Integer.MAX_VALUE, Flowable.bufferSize())); + return RxJavaPlugins.onAssembly(new FlowableFlatMapSinglePublisher<>(sources, Functions.identity(), false, Integer.MAX_VALUE)); } /** @@ -1212,7 +1208,7 @@ public static Flowable merge( ) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); - return merge(Flowable.fromArray(source1, source2)); + return Flowable.fromArray(source1, source2).flatMapSingle(Functions.identity(), false, Integer.MAX_VALUE); } /** @@ -1265,7 +1261,7 @@ public static Flowable merge( Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); - return merge(Flowable.fromArray(source1, source2, source3)); + return Flowable.fromArray(source1, source2, source3).flatMapSingle(Functions.identity(), false, Integer.MAX_VALUE); } /** @@ -1321,7 +1317,7 @@ public static Flowable merge( Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); Objects.requireNonNull(source4, "source4 is null"); - return merge(Flowable.fromArray(source1, source2, source3, source4)); + return Flowable.fromArray(source1, source2, source3, source4).flatMapSingle(Functions.identity(), false, Integer.MAX_VALUE); } /** @@ -1360,7 +1356,7 @@ public static Flowable merge( @SchedulerSupport(SchedulerSupport.NONE) @SafeVarargs public static Flowable mergeArray(SingleSource... sources) { - return Flowable.fromArray(sources).flatMapSingle(Functions.identity(), false, sources.length); + return Flowable.fromArray(sources).flatMapSingle(Functions.identity(), false, Math.max(1, sources.length)); } /** @@ -1396,7 +1392,7 @@ public static Flowable mergeArray(SingleSource... sources) { @SafeVarargs @NonNull public static Flowable mergeArrayDelayError(@NonNull SingleSource... sources) { - return Flowable.fromArray(sources).flatMapSingle(Functions.identity(), true, sources.length); + return Flowable.fromArray(sources).flatMapSingle(Functions.identity(), true, Math.max(1, sources.length)); } /** @@ -1423,7 +1419,7 @@ public static Flowable mergeArrayDelayError(@NonNull SingleSource Flowable mergeDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { - return mergeDelayError(Flowable.fromIterable(sources)); + return Flowable.fromIterable(sources).flatMapSingle(Functions.identity(), true, Integer.MAX_VALUE); } /** @@ -1449,10 +1445,9 @@ public static Flowable mergeDelayError(@NonNull Iterable<@NonNull ? exten @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) - @SuppressWarnings({ "unchecked", "rawtypes" }) public static Flowable mergeDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { Objects.requireNonNull(sources, "sources is null"); - return RxJavaPlugins.onAssembly(new FlowableFlatMapPublisher(sources, SingleInternalHelper.toFlowable(), true, Integer.MAX_VALUE, Flowable.bufferSize())); + return RxJavaPlugins.onAssembly(new FlowableFlatMapSinglePublisher<>(sources, Functions.identity(), true, Integer.MAX_VALUE)); } /** @@ -1490,7 +1485,7 @@ public static Flowable mergeDelayError( ) { Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); - return mergeDelayError(Flowable.fromArray(source1, source2)); + return Flowable.fromArray(source1, source2).flatMapSingle(Functions.identity(), true, Integer.MAX_VALUE); } /** @@ -1532,7 +1527,7 @@ public static Flowable mergeDelayError( Objects.requireNonNull(source1, "source1 is null"); Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); - return mergeDelayError(Flowable.fromArray(source1, source2, source3)); + return Flowable.fromArray(source1, source2, source3).flatMapSingle(Functions.identity(), true, Integer.MAX_VALUE); } /** @@ -1577,7 +1572,7 @@ public static Flowable mergeDelayError( Objects.requireNonNull(source2, "source2 is null"); Objects.requireNonNull(source3, "source3 is null"); Objects.requireNonNull(source4, "source4 is null"); - return mergeDelayError(Flowable.fromArray(source1, source2, source3, source4)); + return Flowable.fromArray(source1, source2, source3, source4).flatMapSingle(Functions.identity(), true, Integer.MAX_VALUE); } /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybePublisher.java similarity index 53% rename from src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapPublisher.java rename to src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybePublisher.java index 0f5be8917d..f300607052 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapMaybePublisher.java @@ -15,31 +15,35 @@ import org.reactivestreams.*; -import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMapMaybe.FlatMapMaybeSubscriber; + +/** + * Maps upstream values into MaybeSources and merges their signals into one sequence. + * @param the source value type + * @param the result value type + */ +public final class FlowableFlatMapMaybePublisher extends Flowable { -public final class FlowableFlatMapPublisher extends Flowable { final Publisher source; - final Function> mapper; + + final Function> mapper; + final boolean delayErrors; + final int maxConcurrency; - final int bufferSize; - public FlowableFlatMapPublisher(Publisher source, - Function> mapper, - boolean delayErrors, int maxConcurrency, int bufferSize) { + public FlowableFlatMapMaybePublisher(Publisher source, Function> mapper, + boolean delayError, int maxConcurrency) { this.source = source; this.mapper = mapper; - this.delayErrors = delayErrors; + this.delayErrors = delayError; this.maxConcurrency = maxConcurrency; - this.bufferSize = bufferSize; } @Override - protected void subscribeActual(Subscriber s) { - if (FlowableScalarXMap.tryScalarXMapSubscribe(source, s, mapper)) { - return; - } - source.subscribe(FlowableFlatMap.subscribe(s, mapper, delayErrors, maxConcurrency, bufferSize)); + protected void subscribeActual(Subscriber s) { + source.subscribe(new FlatMapMaybeSubscriber<>(s, mapper, delayErrors, maxConcurrency)); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSinglePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSinglePublisher.java new file mode 100644 index 0000000000..457a728523 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableFlatMapSinglePublisher.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.flowable; + +import org.reactivestreams.*; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.internal.operators.flowable.FlowableFlatMapSingle.FlatMapSingleSubscriber; + +/** + * Maps upstream values into SingleSources and merges their signals into one sequence. + * @param the source value type + * @param the result value type + */ +public final class FlowableFlatMapSinglePublisher extends Flowable { + + final Publisher source; + + final Function> mapper; + + final boolean delayErrors; + + final int maxConcurrency; + + public FlowableFlatMapSinglePublisher(Publisher source, Function> mapper, + boolean delayError, int maxConcurrency) { + this.source = source; + this.mapper = mapper; + this.delayErrors = delayError; + this.maxConcurrency = maxConcurrency; + } + + @Override + protected void subscribeActual(Subscriber s) { + source.subscribe(new FlatMapSingleSubscriber<>(s, mapper, delayErrors, maxConcurrency)); + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybePublisher.java similarity index 51% rename from src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapPublisher.java rename to src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybePublisher.java index 8ee6afcd87..8651cdcb60 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapMaybePublisher.java @@ -10,40 +10,46 @@ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ -package io.reactivex.rxjava3.internal.operators.flowable; + +package io.reactivex.rxjava3.internal.operators.mixed; import org.reactivestreams.*; -import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.*; import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.internal.operators.mixed.FlowableConcatMapMaybe.ConcatMapMaybeSubscriber; import io.reactivex.rxjava3.internal.util.ErrorMode; -public final class FlowableConcatMapPublisher extends Flowable { +/** + * Maps each upstream item into a {@link MaybeSource}, subscribes to them one after the other terminates + * and relays their success values, optionally delaying any errors till the main and inner sources + * terminate. + *

History: 2.1.11 - experimental + * @param the upstream element type + * @param the output element type + * @since 2.2 + */ +public final class FlowableConcatMapMaybePublisher extends Flowable { final Publisher source; - final Function> mapper; - - final int prefetch; + final Function> mapper; final ErrorMode errorMode; - public FlowableConcatMapPublisher(Publisher source, - Function> mapper, - int prefetch, ErrorMode errorMode) { + final int prefetch; + + public FlowableConcatMapMaybePublisher(Publisher source, + Function> mapper, + ErrorMode errorMode, int prefetch) { this.source = source; this.mapper = mapper; - this.prefetch = prefetch; this.errorMode = errorMode; + this.prefetch = prefetch; } @Override protected void subscribeActual(Subscriber s) { - - if (FlowableScalarXMap.tryScalarXMapSubscribe(source, s, mapper)) { - return; - } - - source.subscribe(FlowableConcatMap.subscribe(s, mapper, prefetch, errorMode)); + source.subscribe(new ConcatMapMaybeSubscriber<>(s, mapper, prefetch, errorMode)); } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSinglePublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSinglePublisher.java new file mode 100644 index 0000000000..5b34314d81 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/FlowableConcatMapSinglePublisher.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.mixed; + +import org.reactivestreams.*; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.internal.operators.mixed.FlowableConcatMapSingle.ConcatMapSingleSubscriber; +import io.reactivex.rxjava3.internal.util.ErrorMode; + +/** + * Maps each upstream item into a {@link SingleSource}, subscribes to them one after the other terminates + * and relays their success values, optionally delaying any errors till the main and inner sources + * terminate. + *

History: 2.1.11 - experimental + * @param the upstream element type + * @param the output element type + * @since 2.2 + */ +public final class FlowableConcatMapSinglePublisher extends Flowable { + + final Publisher source; + + final Function> mapper; + + final ErrorMode errorMode; + + final int prefetch; + + public FlowableConcatMapSinglePublisher(Publisher source, + Function> mapper, + ErrorMode errorMode, int prefetch) { + this.source = source; + this.mapper = mapper; + this.errorMode = errorMode; + this.prefetch = prefetch; + } + + @Override + protected void subscribeActual(Subscriber s) { + source.subscribe(new ConcatMapSingleSubscriber<>(s, mapper, prefetch, errorMode)); + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingle.java index 5fc6b8a520..70d913cd42 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/ObservableConcatMapSingle.java @@ -36,7 +36,7 @@ */ public final class ObservableConcatMapSingle extends Observable { - final Observable source; + final ObservableSource source; final Function> mapper; @@ -44,7 +44,7 @@ public final class ObservableConcatMapSingle extends Observable { final int prefetch; - public ObservableConcatMapSingle(Observable source, + public ObservableConcatMapSingle(ObservableSource source, Function> mapper, ErrorMode errorMode, int prefetch) { this.source = source; diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelper.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelper.java index 95ed46144c..47f8bf1e88 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelper.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelper.java @@ -19,7 +19,6 @@ import org.reactivestreams.Publisher; import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.functions.*; /** @@ -105,19 +104,4 @@ public Iterator> iterator() { public static Iterable> iterableToFlowable(final Iterable> sources) { return new ToFlowableIterable<>(sources); } - - @SuppressWarnings("rawtypes") - enum ToObservable implements Function { - INSTANCE; - @SuppressWarnings("unchecked") - @Override - public Observable apply(SingleSource v) { - return new SingleToObservable(v); - } - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Function, Observable> toObservable() { - return (Function)ToObservable.INSTANCE; - } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelperTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelperTest.java index e551b882d1..5d5e152c1b 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelperTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleInternalHelperTest.java @@ -41,12 +41,6 @@ public void toFlowableEnum() { assertNotNull(SingleInternalHelper.ToFlowable.valueOf("INSTANCE")); } - @Test - public void toObservableEnum() { - assertEquals(1, SingleInternalHelper.ToObservable.values().length); - assertNotNull(SingleInternalHelper.ToObservable.valueOf("INSTANCE")); - } - @Test public void singleIterableToFlowableIterable() { Iterable> it = SingleInternalHelper.iterableToFlowable( diff --git a/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java b/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java index 94cf62d641..401bdcc918 100644 --- a/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java +++ b/src/test/java/io/reactivex/rxjava3/maybe/MaybeTest.java @@ -2514,8 +2514,6 @@ public void mergeArrayDelayError() { Maybe.mergeArrayDelayError(Maybe.error(new TestException()), Maybe.empty(), Maybe.just(1)) .test() .assertFailure(TestException.class, 1); - - assertSame(Flowable.empty(), Maybe.mergeArrayDelayError()); } @Test From b3516b2fbf76643d4fce2bb077de64deaf959f90 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Tue, 28 Jan 2020 16:32:12 +0100 Subject: [PATCH 32/37] 3.x: Fix marble dimensions, add program that checks them (#6890) * 3.x: Fix marble dimensions, add program that checks them * Remove an empty line. --- .../reactivex/rxjava3/core/Completable.java | 26 ++-- .../io/reactivex/rxjava3/core/Flowable.java | 34 +++--- .../java/io/reactivex/rxjava3/core/Maybe.java | 40 +++--- .../io/reactivex/rxjava3/core/Observable.java | 114 +++++++++--------- .../io/reactivex/rxjava3/core/Single.java | 54 ++++----- .../rxjava3/parallel/ParallelFlowable.java | 4 +- .../internal/util/MarbleDimensions.java | 106 ++++++++++++++++ 7 files changed, 242 insertions(+), 136 deletions(-) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index 83e7848a51..cfdd87067d 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -178,7 +178,7 @@ public static Completable complete() { /** * Returns a {@code Completable} which completes only when all sources complete, one after another. *

- * + * *

*
Scheduler:
*
{@code concatArray} does not operate by default on a particular {@link Scheduler}.
@@ -205,7 +205,7 @@ public static Completable concatArray(@NonNull CompletableSource... sources) { /** * Returns a {@code Completable} which completes only when all sources complete, one after another. *

- * + * *

*
Scheduler:
*
{@code concatArrayDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -247,7 +247,7 @@ public static Completable concat(@NonNull Iterable<@NonNull ? extends Completabl /** * Returns a {@code Completable} which completes only when all sources complete, one after another. *

- * + * *

*
Backpressure:
*
The returned {@code Completable} honors the backpressure of the downstream consumer @@ -270,7 +270,7 @@ public static Completable concat(@NonNull Publisher<@NonNull ? extends Completab /** * Returns a {@code Completable} which completes only when all sources complete, one after another. *

- * + * *

*
Backpressure:
*
The returned {@code Completable} honors the backpressure of the downstream consumer @@ -297,7 +297,7 @@ public static Completable concat(@NonNull Publisher<@NonNull ? extends Completab /** * Returns a {@code Completable} which completes only when all sources complete, one after another. *

- * + * *

*
Scheduler:
*
{@code concatDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -989,7 +989,7 @@ public static Completable mergeArrayDelayError(@NonNull CompletableSource... sou * any error emitted by any of the inner {@code CompletableSource}s until all of * them terminate in a way or another. *

- * + * *

*
Scheduler:
*
{@code mergeDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -1200,7 +1200,7 @@ public static Completable switchOnNextDelayError(@NonNull Publisher<@NonNull ? e * Returns a {@code Completable} instance which manages a resource along * with a custom {@link CompletableSource} instance while the subscription is active. *

- * + * *

* This overload disposes eagerly before the terminal event is emitted. *

@@ -1294,7 +1294,7 @@ public static Completable wrap(@NonNull CompletableSource source) { * Returns a {@code Completable} that emits the a terminated event of either this {@code Completable} * or the other {@link CompletableSource}, whichever fires first. *

- * + * *

*
Scheduler:
*
{@code ambWith} does not operate by default on a particular {@link Scheduler}.
@@ -1395,7 +1395,7 @@ public final Completable ambWith(@NonNull CompletableSource other) { * propagated to the downstream observer and will result in skipping the subscription to the next * {@code MaybeSource}. *

- * + * *

*
Scheduler:
*
{@code andThen} does not operate by default on a particular {@link Scheduler}.
@@ -1443,7 +1443,7 @@ public final Completable andThen(@NonNull CompletableSource next) { * Subscribes to and awaits the termination of this {@code Completable} instance in a blocking manner and * rethrows any exception emitted. *

- * + * *

*
Scheduler:
*
{@code blockingAwait} does not operate by default on a particular {@link Scheduler}.
@@ -1665,7 +1665,7 @@ public final Completable concatWith(@NonNull CompletableSource other) { /** * Returns a {@code Completable} which delays the emission of the completion event by the given time. *

- * + * *

*
Scheduler:
*
{@code delay} does operate by default on the {@code computation} {@link Scheduler}.
@@ -1955,7 +1955,7 @@ public final Completable doOnSubscribe(@NonNull Consumer onS * Returns a {@code Completable} instance that calls the given {@code onTerminate} {@link Action} just before this {@code Completable} * completes normally or with an exception. *

- * + * *

*
Scheduler:
*
{@code doOnTerminate} does not operate by default on a particular {@link Scheduler}.
@@ -1978,7 +1978,7 @@ public final Completable doOnTerminate(@NonNull Action onTerminate) { * Returns a {@code Completable} instance that calls the given {@code onAfterTerminate} {@link Action} after this {@code Completable} * completes normally or with an exception. *

- * + * *

*
Scheduler:
*
{@code doAfterTerminate} does not operate by default on a particular {@link Scheduler}.
diff --git a/src/main/java/io/reactivex/rxjava3/core/Flowable.java b/src/main/java/io/reactivex/rxjava3/core/Flowable.java index 453c9e4bba..58ffd3d6f8 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Flowable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Flowable.java @@ -1964,7 +1964,7 @@ public static Flowable error(@NonNull Throwable throwable) { * Returns a {@code Flowable} instance that runs the given {@link Action} for each subscriber and * emits either its exception or simply completes. *

- * + * *

*
Backpressure:
*
This source doesn't produce any elements and effectively ignores downstream backpressure.
@@ -9934,7 +9934,7 @@ public final Flowable filter(@NonNull Predicate predicate) { * Returns a {@link Maybe} that emits only the very first item emitted by this {@code Flowable} or * completes if this {@code Flowable} is empty. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in a bounded manner.
@@ -9957,7 +9957,7 @@ public final Maybe firstElement() { * Returns a {@link Single} that emits only the very first item emitted by this {@code Flowable}, or a default * item if this {@code Flowable} completes without emitting anything. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in a bounded manner.
@@ -10561,7 +10561,7 @@ public final Completable flatMapCompletable(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The current {@code Flowable}s is @@ -10592,7 +10592,7 @@ public final Flowable flatMapIterable(@NonNull Function - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream. The current {@code Flowable}s is @@ -14336,7 +14336,7 @@ public final Flowable sample(long period, @NonNull TimeUnit unit) { * Returns a {@code Flowable} that emits the most recently emitted item (if any) emitted by the current {@code Flowable} * within periodic time intervals and optionally emit the very last upstream item when the upstream completes. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time to control data flow.
@@ -14407,7 +14407,7 @@ public final Flowable sample(long period, @NonNull TimeUnit unit, @NonNull Sc * within periodic time intervals, where the intervals are defined on a particular {@link Scheduler} * and optionally emit the very last upstream item when the upstream completes. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses time to control data flow.
@@ -14448,7 +14448,7 @@ public final Flowable sample(long period, @NonNull TimeUnit unit, @NonNull Sc * emits the most recently emitted item (if any) emitted by the current {@code Flowable} since the previous * emission from the {@code sampler} {@code Publisher}. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses the emissions of the {@code sampler} @@ -14480,7 +14480,7 @@ public final Flowable sample(@NonNull Publisher sampler) { * emission from the {@code sampler} {@code Publisher} * and optionally emit the very last upstream item when the upstream or other {@code Publisher} complete. *

- * + * *

*
Backpressure:
*
This operator does not support backpressure as it uses the emissions of the {@code sampler} @@ -14759,7 +14759,7 @@ public final Single single(@NonNull T defaultItem) { * if this {@code Flowable} completes without emitting any items a {@link NoSuchElementException} will be signaled and * if this {@code Flowable} emits more than one item, an {@link IllegalArgumentException} will be signaled. *

- * + * *

*
Backpressure:
*
The operator honors backpressure from downstream and consumes the current {@code Flowable} in an @@ -15728,7 +15728,7 @@ public final Flowable subscribeOn(@NonNull Scheduler scheduler, boolean reque * Returns a {@code Flowable} that emits the items emitted by the current {@code Flowable} or the items of an alternate * {@link Publisher} if the current {@code Flowable} is empty. *

- * + * *

*
Backpressure:
*
If the current {@code Flowable} is empty, the alternate {@code Publisher} is expected to honor backpressure. @@ -15835,7 +15835,7 @@ public final Flowable switchMap(@NonNull Function - * + * *

* Since a {@code CompletableSource} doesn't produce any items, the resulting reactive type of * this operator is a {@link Completable} that can only indicate successful completion or @@ -16852,7 +16852,7 @@ public final Flowable throttleLast(long intervalDuration, @NonNull TimeUnit u * item from upstream, then periodically emitting the latest item (if any) when * the specified timeout elapses between them. *

- * + * *

* Unlike the option with {@link #throttleLatest(long, TimeUnit, boolean)}, the very last item being held back * (if any) is not emitted when the upstream completes. @@ -16891,7 +16891,7 @@ public final Flowable throttleLatest(long timeout, @NonNull TimeUnit unit) { * item from upstream, then periodically emitting the latest item (if any) when * the specified timeout elapses between them. *

- * + * *

* If no items were emitted from the upstream during this timeout phase, the next * upstream item is emitted immediately and the timeout window starts from then. @@ -16930,7 +16930,7 @@ public final Flowable throttleLatest(long timeout, @NonNull TimeUnit unit, bo * item from upstream, then periodically emitting the latest item (if any) when * the specified timeout elapses between them. *

- * + * *

* Unlike the option with {@link #throttleLatest(long, TimeUnit, Scheduler, boolean)}, the very last item being held back * (if any) is not emitted when the upstream completes. @@ -16970,7 +16970,7 @@ public final Flowable throttleLatest(long timeout, @NonNull TimeUnit unit, @N * item from upstream, then periodically emitting the latest item (if any) when * the specified timeout elapses between them. *

- * + * *

* If no items were emitted from the upstream during this timeout phase, the next * upstream item is emitted immediately and the timeout window starts from then. @@ -19764,7 +19764,7 @@ public final CompletionStage lastStage(@Nullable T defaultItem) { * Signals the first upstream item or a {@link NoSuchElementException} if the upstream is empty via * a {@link CompletionStage}. *

- * + * *

* The upstream can be canceled by converting the resulting {@code CompletionStage} into * {@link CompletableFuture} via {@link CompletionStage#toCompletableFuture()} and diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index d4116406b4..37ce1e99e2 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -117,7 +117,7 @@ public abstract class Maybe implements MaybeSource { * Runs multiple {@link MaybeSource}s provided by an {@link Iterable} sequence and * signals the events of the first one that signals (disposing the rest). *

- * + * *

*
Scheduler:
*
{@code amb} does not operate by default on a particular {@link Scheduler}.
@@ -196,7 +196,7 @@ public static Flowable concat(@NonNull Iterable<@NonNull ? extends MaybeS /** * Returns a {@link Flowable} that emits the items emitted by two {@link MaybeSource}s, one after the other. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -226,7 +226,7 @@ public static Flowable concat(@NonNull MaybeSource source1, /** * Returns a {@link Flowable} that emits the items emitted by three {@link MaybeSource}s, one after the other. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -260,7 +260,7 @@ public static Flowable concat( /** * Returns a {@link Flowable} that emits the items emitted by four {@link MaybeSource}s, one after the other. *

- * + * *

*
Backpressure:
*
The returned {@code Flowable} honors the backpressure of the downstream consumer.
@@ -425,7 +425,7 @@ public static Flowable concatArrayDelayError(@NonNull MaybeSource - * + * *
*
Backpressure:
*
The operator honors backpressure from downstream.
@@ -1227,7 +1227,7 @@ public static Flowable merge(@NonNull Publisher<@NonNull ? extends MaybeS * Flattens a {@link MaybeSource} that emits a {@code MaybeSource} into a single {@code MaybeSource} that emits the item * emitted by the nested {@code MaybeSource}, without any transformation. *

- * + * *

*
Scheduler:
*
{@code merge} does not operate by default on a particular {@link Scheduler}.
@@ -1771,7 +1771,7 @@ public static Maybe never() { * Returns a {@link Single} that emits a {@link Boolean} value that indicates whether two {@link MaybeSource} sequences are the * same by comparing the items emitted by each {@code MaybeSource} pairwise. *

- * + * *

*
Scheduler:
*
{@code sequenceEqual} does not operate by default on a particular {@link Scheduler}.
@@ -2562,7 +2562,7 @@ public static Maybe zip( * {@code Function} passed to the method would trigger a {@link ClassCastException}. * *

- * + * *

This operator terminates eagerly if any of the source {@code MaybeSource}s signal an {@code onError} or {@code onComplete}. This * also means it is possible some sources may not get subscribed to at all. *

@@ -3630,7 +3630,7 @@ public final Maybe filter(@NonNull Predicate predicate) { * Returns a {@code Maybe} that is based on applying a specified function to the item emitted by the current {@code Maybe}, * where that function returns a {@link MaybeSource}. *

- * + * *

*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -3782,7 +3782,7 @@ public final Observable flattenAsObservable(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapObservable} does not operate by default on a particular {@link Scheduler}.
@@ -3807,7 +3807,7 @@ public final Observable flatMapObservable(@NonNull Function - * + * *
*
Backpressure:
*
The returned {@code Flowable} honors the downstream backpressure.
@@ -3864,7 +3864,7 @@ public final Single flatMapSingle(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapSingleElement} does not operate by default on a particular {@link Scheduler}.
@@ -3935,7 +3935,7 @@ public final Maybe hide() { /** * Returns a {@link Completable} that ignores the item emitted by the current {@code Maybe} and only calls {@code onComplete} or {@code onError}. *

- * + * *

*
Scheduler:
*
{@code ignoreElement} does not operate by default on a particular {@link Scheduler}.
@@ -4207,7 +4207,7 @@ public final Flowable mergeWith(@NonNull MaybeSource other) { * Wraps a {@code Maybe} to emit its item (or notify of its error) on a specified {@link Scheduler}, * asynchronously. *

- * + * *

*
Scheduler:
*
you specify which {@code Scheduler} this operator will use.
@@ -5137,7 +5137,7 @@ public final void subscribe(@NonNull MaybeObserver observer) { /** * Asynchronously subscribes subscribers to this {@code Maybe} on the specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
you specify which {@code Scheduler} this operator will use.
@@ -5194,7 +5194,7 @@ public final Maybe subscribeOn(@NonNull Scheduler scheduler) { * Returns a {@code Maybe} that emits the items emitted by the current {@code Maybe} or the items of an alternate * {@link MaybeSource} if the current {@code Maybe} is empty. *

- * + * *

*
Scheduler:
*
{@code switchIfEmpty} does not operate by default on a particular {@link Scheduler}.
@@ -5217,7 +5217,7 @@ public final Maybe switchIfEmpty(@NonNull MaybeSource other) { * Returns a {@link Single} that emits the items emitted by the current {@code Maybe} or the item of an alternate * {@link SingleSource} if the current {@code Maybe} is empty. *

- * + * *

*
Scheduler:
*
{@code switchIfEmpty} does not operate by default on a particular {@link Scheduler}.
@@ -5739,7 +5739,7 @@ public final Maybe timeout(@NonNull Publisher timeoutIndicator, @NonNu * Returns a {@code Maybe} which makes sure when a {@link MaybeObserver} disposes the {@link Disposable}, * that call is propagated up on the specified {@link Scheduler}. *

- * + * *

*
Scheduler:
*
{@code unsubscribeOn} calls {@code dispose()} of the upstream on the {@code Scheduler} you specify.
@@ -6002,7 +6002,7 @@ public final CompletionStage toCompletionStage(@Nullable T defaultItem) { * Maps the upstream succecss value into a Java {@link Stream} and emits its * items to the downstream consumer as a {@link Flowable}. *

- * + * *

* The operator closes the {@code Stream} upon cancellation and when it terminates. The exceptions raised when * closing a {@code Stream} are routed to the global error handler ({@link RxJavaPlugins#onError(Throwable)}. @@ -6046,7 +6046,7 @@ public final Flowable flattenStreamAsFlowable(@NonNull Function + * *

* The operator closes the {@code Stream} upon cancellation and when it terminates. The exceptions raised when * closing a {@code Stream} are routed to the global error handler ({@link RxJavaPlugins#onError(Throwable)}. diff --git a/src/main/java/io/reactivex/rxjava3/core/Observable.java b/src/main/java/io/reactivex/rxjava3/core/Observable.java index 6db7ce3cc1..9eeb169871 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Observable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Observable.java @@ -1271,7 +1271,7 @@ public static Observable concatArrayDelayError(@NonNull ObservableSource< /** * Concatenates an array of {@link ObservableSource}s eagerly into a single stream of values. *

- * + * *

* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * {@code ObservableSource}s. The operator buffers the values emitted by these {@code ObservableSource}s and then drains them @@ -1688,7 +1688,7 @@ public static Observable empty() { * Returns an {@code Observable} that invokes an {@link Observer}'s {@link Observer#onError onError} method when the * {@code Observer} subscribes to it. *

- * + * *

*
Scheduler:
*
{@code error} does not operate by default on a particular {@link Scheduler}.
@@ -1714,7 +1714,7 @@ public static Observable error(@NonNull Supplier sup * Returns an {@code Observable} that invokes an {@link Observer}'s {@link Observer#onError onError} method when the * {@code Observer} subscribes to it. *

- * + * *

*
Scheduler:
*
{@code error} does not operate by default on a particular {@link Scheduler}.
@@ -1740,7 +1740,7 @@ public static Observable error(@NonNull Throwable throwable) { * Returns an {@code Observable} instance that runs the given {@link Action} for each subscriber and * emits either its exception or simply completes. *

- * + * *

*
Scheduler:
*
{@code fromAction} does not operate by default on a particular {@link Scheduler}.
@@ -1941,7 +1941,7 @@ public static Observable fromFuture(@NonNull Future future, /** * Converts an {@link Iterable} sequence into an {@code Observable} that emits the items in the sequence. *

- * + * *

*
Scheduler:
*
{@code fromIterable} does not operate by default on a particular {@link Scheduler}.
@@ -5198,7 +5198,7 @@ public static Observable zipArray( * Returns a {@link Single} that emits a {@link Boolean} that indicates whether all of the items emitted by the current * {@code Observable} satisfy a condition. *

- * + * *

*
Scheduler:
*
{@code all} does not operate by default on a particular {@link Scheduler}.
@@ -5275,7 +5275,7 @@ public final Single any(@NonNull Predicate predicate) { * Returns the first item emitted by the current {@code Observable}, or throws * {@link NoSuchElementException} if it emits no items. *

- * + * *

*
Scheduler:
*
{@code blockingFirst} does not operate by default on a particular {@link Scheduler}.
@@ -5703,7 +5703,7 @@ public final void blockingSubscribe() { /** * Subscribes to the source and calls the given callbacks on the current thread. *

- * + * *

* If the {@code Observable} emits an error, it is wrapped into an * {@link OnErrorNotImplementedException} @@ -5732,7 +5732,7 @@ public final void blockingSubscribe(@NonNull Consumer onNext) { /** * Subscribes to the source and calls the given callbacks on the current thread. *

- * + * *

* Note that calling this method will block the caller thread until the upstream terminates * normally or with an error. Therefore, calling this method from special threads such as the @@ -6748,7 +6748,7 @@ public final Observable concatMap(@NonNull Function - * + * *

* Note that there is no guarantee where the given {@code mapper} function will be executed; it could be on the subscribing thread, * on the upstream thread signaling the new item to be mapped or on the thread where the inner source terminates. To ensure @@ -6777,7 +6777,7 @@ public final Observable concatMapDelayError(@NonNull Function - * + * *

* Note that there is no guarantee where the given {@code mapper} function will be executed; it could be on the subscribing thread, * on the upstream thread signaling the new item to be mapped or on the thread where the inner source terminates. To ensure @@ -6823,7 +6823,7 @@ public final Observable concatMapDelayError(@NonNull Function - * + * *

*
Scheduler:
*
{@code concatMapDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -6863,7 +6863,7 @@ public final Observable concatMapDelayError(@NonNull Function - * + * *
*
Scheduler:
*
This method does not operate by default on a particular {@link Scheduler}.
@@ -6890,7 +6890,7 @@ public final Observable concatMapEager(@NonNull Function - * + * *
*
Scheduler:
*
This method does not operate by default on a particular {@link Scheduler}.
@@ -6990,7 +6990,7 @@ public final Observable concatMapEagerDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapCompletable} does not operate by default on a particular {@link Scheduler}.
@@ -7013,7 +7013,7 @@ public final Completable concatMapCompletable(@NonNull Function - * + * *
*
Scheduler:
*
{@code concatMapCompletable} does not operate by default on a particular {@link Scheduler}.
@@ -8366,7 +8366,7 @@ public final Observable doAfterTerminate(@NonNull Action onAfterTerminate) { *

Note that the {@code onFinally} action is shared between subscriptions and as such * should be thread-safe. *

- * + * *

*
Scheduler:
*
{@code doFinally} does not operate by default on a particular {@link Scheduler}.
@@ -8686,7 +8686,7 @@ public final Maybe elementAt(long index) { * Returns a {@link Single} that emits the item found at a specified index in a sequence of emissions from * the current {@code Observable}, or a default item if that index is out of range. *

- * + * *

*
Scheduler:
*
{@code elementAt} does not operate by default on a particular {@link Scheduler}.
@@ -8788,7 +8788,7 @@ public final Maybe firstElement() { * Returns a {@link Single} that emits only the very first item emitted by the current {@code Observable}, or a default item * if the current {@code Observable} completes without emitting any items. *

- * + * *

*
Scheduler:
*
{@code first} does not operate by default on a particular {@link Scheduler}.
@@ -8811,7 +8811,7 @@ public final Single first(@NonNull T defaultItem) { * Returns a {@link Single} that emits only the very first item emitted by the current {@code Observable} or * signals a {@link NoSuchElementException} if the current {@code Observable} is empty. *

- * + * *

*
Scheduler:
*
{@code firstOrError} does not operate by default on a particular {@link Scheduler}.
@@ -8888,7 +8888,7 @@ public final Observable flatMap(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -8922,7 +8922,7 @@ public final Observable flatMap(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -9050,7 +9050,7 @@ public final Observable flatMap( * {@code ObservableSource}s and emitting the results of this merger, while limiting the maximum number of concurrent * subscriptions to these {@code ObservableSource}s. *

- * + * *

*
Scheduler:
*
{@code flatMap} does not operate by default on a particular {@link Scheduler}.
@@ -9282,7 +9282,7 @@ public final Completable flatMapCompletable(@NonNull Function - * + * *
*
Scheduler:
*
{@code flatMapCompletable} does not operate by default on a particular {@link Scheduler}.
@@ -9487,7 +9487,7 @@ public final Disposable forEach(@NonNull Consumer onNext) { * Subscribes to the {@link ObservableSource} and calls a {@link Predicate} for each item of the current {@code Observable}, * on its emission thread, until the predicate returns {@code false}. *

- * + * *

* If the {@code Observable} emits an error, it is wrapped into an * {@link OnErrorNotImplementedException} @@ -10668,7 +10668,7 @@ public final Observable onErrorReturnItem(@NonNull T item) { * Nulls out references to the upstream producer and downstream {@link Observer} if * the sequence is terminated or downstream calls {@code dispose()}. *

- * + * *

*
Scheduler:
*
{@code onTerminateDetach} does not operate by default on a particular {@link Scheduler}.
@@ -10923,7 +10923,7 @@ public final Observable repeat(long times) { * Returns an {@code Observable} that repeats the sequence of items emitted by the current {@code Observable} until * the provided stop function returns {@code true}. *

- * + * *

*
Scheduler:
*
{@code repeatUntil} does not operate by default on a particular {@link Scheduler}.
@@ -11031,7 +11031,7 @@ public final Observable replay(@NonNull Function, ? * Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. *

- * + * *

*
Scheduler:
*
This version of {@code replay} does not operate by default on a particular {@link Scheduler}.
@@ -11067,7 +11067,7 @@ public final Observable replay(@NonNull Function, ? * Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. *

- * + * *

*
Scheduler:
*
This version of {@code replay} does not operate by default on a particular {@link Scheduler}.
@@ -11142,7 +11142,7 @@ public final Observable replay(@NonNull Function, ? * Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -11189,7 +11189,7 @@ public final Observable replay(@NonNull Function, ? * Note that due to concurrency requirements, {@code replay(bufferSize)} may hold strong references to more than * {@code bufferSize} source emissions. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -11234,7 +11234,7 @@ public final Observable replay(@NonNull Function, ? * emitted by a {@link ConnectableObservable} that shares a single subscription to the current {@code Observable}, * replaying all items that were emitted within a specified time window. *

- * + * *

*
Scheduler:
*
This version of {@code replay} operates by default on the {@code computation} {@link Scheduler}.
@@ -11265,7 +11265,7 @@ public final Observable replay(@NonNull Function, ? * emitted by a {@link ConnectableObservable} that shares a single subscription to the current {@code Observable}, * replaying all items that were emitted within a specified time window. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -11302,7 +11302,7 @@ public final Observable replay(@NonNull Function, ? * emitted by a {@link ConnectableObservable} that shares a single subscription to the current {@code Observable}, * replaying all items that were emitted within a specified time window. *

- * + * *

*
Scheduler:
*
You specify which {@link Scheduler} this operator will use.
@@ -11654,7 +11654,7 @@ public final Observable retry() { * Returns an {@code Observable} that mirrors the current {@code Observable}, resubscribing to it if it calls {@code onError} * and the predicate returns {@code true} for that specific exception and retry count. *

- * + * *

*
Scheduler:
*
{@code retry} does not operate by default on a particular {@link Scheduler}.
@@ -11681,7 +11681,7 @@ public final Observable retry(@NonNull BiPredicate - * + * *

* If the current {@code Observable} calls {@link Observer#onError}, this method will resubscribe to the current * {@code Observable} for a maximum of {@code count} resubscriptions rather than propagating the @@ -11712,7 +11712,7 @@ public final Observable retry(long times) { /** * Retries at most times or until the predicate returns {@code false}, whichever happens first. *

- * + * *

*
Scheduler:
*
{@code retry} does not operate by default on a particular {@link Scheduler}.
@@ -11738,7 +11738,7 @@ public final Observable retry(long times, @NonNull Predicate - * + * *
*
Scheduler:
*
{@code retry} does not operate by default on a particular {@link Scheduler}.
@@ -11758,7 +11758,7 @@ public final Observable retry(@NonNull Predicate predicate /** * Retries until the given stop function returns {@code true}. *

- * + * *

*
Scheduler:
*
{@code retryUntil} does not operate by default on a particular {@link Scheduler}.
@@ -11911,7 +11911,7 @@ public final Observable sample(long period, @NonNull TimeUnit unit) { * Returns an {@code Observable} that emits the most recently emitted item (if any) emitted by the current {@code Observable} * within periodic time intervals and optionally emit the very last upstream item when the upstream completes. *

- * + * *

*
Scheduler:
*
{@code sample} operates by default on the {@code computation} {@link Scheduler}.
@@ -11974,7 +11974,7 @@ public final Observable sample(long period, @NonNull TimeUnit unit, @NonNull * within periodic time intervals, where the intervals are defined on a particular {@link Scheduler} * and optionally emit the very last upstream item when the upstream completes. *

- * + * *

*
Scheduler:
*
You specify which {@code Scheduler} this operator will use.
@@ -12011,7 +12011,7 @@ public final Observable sample(long period, @NonNull TimeUnit unit, @NonNull * emits the most recently emitted item (if any) emitted by the current {@code Observable} since the previous * emission from the {@code sampler} {@code ObservableSource}. *

- * + * *

*
Scheduler:
*
This version of {@code sample} does not operate by default on a particular {@link Scheduler}.
@@ -12038,7 +12038,7 @@ public final Observable sample(@NonNull ObservableSource sampler) { * emission from the {@code sampler} {@code ObservableSource} * and optionally emit the very last upstream item when the upstream or other {@code ObservableSource} complete. *

- * + * *

*
Scheduler:
*
This version of {@code sample} does not operate by default on a particular {@link Scheduler}.
@@ -12283,7 +12283,7 @@ public final Single single(@NonNull T defaultItem) { * if the current {@code Observable} completes without emitting any items or emits more than one item a * {@link NoSuchElementException} or {@link IllegalArgumentException} will be signaled respectively. *

- * + * *

*
Scheduler:
*
{@code singleOrError} does not operate by default on a particular {@link Scheduler}.
@@ -12708,7 +12708,7 @@ public final Observable startWithIterable(@NonNull Iterable<@NonNull ? extend * Returns an {@code Observable} which first runs the other {@link CompletableSource} * then the current {@code Observable} if the other completed normally. *

- * + * *

*
Scheduler:
*
{@code startWith} does not operate by default on a particular {@link Scheduler}.
@@ -13052,7 +13052,7 @@ public final Observable subscribeOn(@NonNull Scheduler scheduler) { * Returns an {@code Observable} that emits the items emitted by the current {@code Observable} or the items of an alternate * {@link ObservableSource} if the current {@code Observable} is empty. *

- * + * *

*
Scheduler:
*
{@code switchIfEmpty} does not operate by default on a particular {@link Scheduler}.
@@ -13150,7 +13150,7 @@ public final Observable switchMap(@NonNull Function - * + * *

* Since a {@code CompletableSource} doesn't produce any items, the resulting reactive type of * this operator is a {@link Completable} that can only indicate successful completion or @@ -13238,7 +13238,7 @@ public final Completable switchMapCompletableDelayError(@NonNull Function - * + * *

*
Scheduler:
*
{@code switchMapMaybe} does not operate by default on a particular {@link Scheduler}.
@@ -13275,7 +13275,7 @@ public final Observable switchMapMaybe(@NonNull Function - * + * *
*
Scheduler:
*
{@code switchMapMaybeDelayError} does not operate by default on a particular {@link Scheduler}.
@@ -13306,7 +13306,7 @@ public final Observable switchMapMaybeDelayError(@NonNull Function - * + * *
*
Scheduler:
*
{@code switchMapSingle} does not operate by default on a particular {@link Scheduler}.
@@ -14030,7 +14030,7 @@ public final Observable throttleLast(long intervalDuration, @NonNull TimeUnit * item from upstream, then periodically emitting the latest item (if any) when * the specified timeout elapses between them. *

- * + * *

* Unlike the option with {@link #throttleLatest(long, TimeUnit, boolean)}, the very last item being held back * (if any) is not emitted when the upstream completes. @@ -14063,7 +14063,7 @@ public final Observable throttleLatest(long timeout, @NonNull TimeUnit unit) * item from upstream, then periodically emitting the latest item (if any) when * the specified timeout elapses between them. *

- * + * *

* If no items were emitted from the upstream during this timeout phase, the next * upstream item is emitted immediately and the timeout window starts from then. @@ -14096,7 +14096,7 @@ public final Observable throttleLatest(long timeout, @NonNull TimeUnit unit, * item from upstream, then periodically emitting the latest item (if any) when * the specified timeout elapses between them. *

- * + * *

* Unlike the option with {@link #throttleLatest(long, TimeUnit, Scheduler, boolean)}, the very last item being held back * (if any) is not emitted when the upstream completes. @@ -14130,7 +14130,7 @@ public final Observable throttleLatest(long timeout, @NonNull TimeUnit unit, * item from upstream, then periodically emitting the latest item (if any) when * the specified timeout elapses between them. *

- * + * *

* If no items were emitted from the upstream during this timeout phase, the next * upstream item is emitted immediately and the timeout window starts from then. @@ -15085,7 +15085,7 @@ public final Single> toMap( * *

  • {@link BackpressureStrategy#LATEST} *

    - * + * *

  • *
  • {@link BackpressureStrategy#ERROR} *

    @@ -15093,7 +15093,7 @@ public final Single> toMap( *

  • *
  • {@link BackpressureStrategy#MISSING} *

    - * + * *

  • * *
    @@ -15259,7 +15259,7 @@ public final Flowable toFlowable(@NonNull BackpressureStrategy strategy) { * Return an {@code Observable} that schedules the downstream {@link Observer}s' {@code dispose} calls * aimed at the current {@code Observable} on the given {@link Scheduler}. *

    - * + * *

    *
    Scheduler:
    *
    You specify which {@code Scheduler} this operator will use.
    diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 7db69e5bc5..cab4d3c073 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -119,7 +119,7 @@ public abstract class Single<@NonNull T> implements SingleSource { * Runs multiple {@link SingleSource}s and signals the events of the first one that signals (disposing * the rest). *

    - * + * *

    *
    Scheduler:
    *
    {@code amb} does not operate by default on a particular {@link Scheduler}.
    @@ -143,7 +143,7 @@ public static Single amb(@NonNull Iterable<@NonNull ? extends SingleSourc * Runs multiple {@link SingleSource}s and signals the events of the first one that signals (disposing * the rest). *

    - * + * *

    *
    Scheduler:
    *
    {@code ambArray} does not operate by default on a particular {@link Scheduler}.
    @@ -224,7 +224,7 @@ public static Observable concat(@NonNull ObservableSource - * + * *
    *
    Backpressure:
    *
    The returned {@link Flowable} honors the backpressure of the downstream consumer @@ -1707,7 +1707,7 @@ public static Flowable switchOnNext(@NonNull Publisher<@NonNull ? extends * exposing the success items as a {@link Flowable} sequence and delaying all errors from * all of them until all terminate. *

    - * + * *

    *
    Backpressure:
    *
    The {@code sources} {@code Publisher} is consumed in an unbounded manner (requesting {@link Long#MAX_VALUE}). @@ -1907,7 +1907,7 @@ public static Single zip(@NonNull Iterable<@NonNull ? extends SingleSo * Returns a {@code Single} that emits the results of a specified combiner function applied to two items emitted by * two other {@link SingleSource}s. *

    - * + * *

    *
    Scheduler:
    *
    {@code zip} does not operate by default on a particular {@link Scheduler}.
    @@ -1944,7 +1944,7 @@ public static Single zip( * Returns a {@code Single} that emits the results of a specified combiner function applied to three items emitted * by three other {@link SingleSource}s. *

    - * + * *

    *
    Scheduler:
    *
    {@code zip} does not operate by default on a particular {@link Scheduler}.
    @@ -1986,7 +1986,7 @@ public static Single zip( * Returns a {@code Single} that emits the results of a specified combiner function applied to four items * emitted by four other {@link SingleSource}s. *

    - * + * *

    *
    Scheduler:
    *
    {@code zip} does not operate by default on a particular {@link Scheduler}.
    @@ -2032,7 +2032,7 @@ public static Single zip( * Returns a {@code Single} that emits the results of a specified combiner function applied to five items * emitted by five other {@link SingleSource}s. *

    - * + * *

    *
    Scheduler:
    *
    {@code zip} does not operate by default on a particular {@link Scheduler}.
    @@ -2084,7 +2084,7 @@ public static Single zip( * Returns a {@code Single} that emits the results of a specified combiner function applied to six items * emitted by six other {@link SingleSource}s. *

    - * + * *

    *
    Scheduler:
    *
    {@code zip} does not operate by default on a particular {@link Scheduler}.
    @@ -2140,7 +2140,7 @@ public static Single zip( * Returns a {@code Single} that emits the results of a specified combiner function applied to seven items * emitted by seven other {@link SingleSource}s. *

    - * + * *

    *
    Scheduler:
    *
    {@code zip} does not operate by default on a particular {@link Scheduler}.
    @@ -2201,7 +2201,7 @@ public static Single zip( * Returns a {@code Single} that emits the results of a specified combiner function applied to eight items * emitted by eight other {@link SingleSource}s. *

    - * + * *

    *
    Scheduler:
    *
    {@code zip} does not operate by default on a particular {@link Scheduler}.
    @@ -2266,7 +2266,7 @@ public static Single zip( * Returns a {@code Single} that emits the results of a specified combiner function applied to nine items * emitted by nine other {@link SingleSource}s. *

    - * + * *

    *
    Scheduler:
    *
    {@code zip} does not operate by default on a particular {@link Scheduler}.
    @@ -2895,7 +2895,7 @@ public final Single delaySubscription(long time, @NonNull TimeUnit unit, @Non /** * Calls the specified consumer with the success item after this item has been emitted to the downstream. *

    - * + * *

    * Note that the {@code doAfterSuccess} action is shared between subscriptions and as such * should be thread-safe. @@ -2920,7 +2920,7 @@ public final Single doAfterSuccess(@NonNull Consumer onAfterSucces /** * Registers an {@link Action} to be called after this {@code Single} invokes either {@code onSuccess} or {@code onError}. *

    - * + * *

    * Note that the {@code doAfterTerminate} action is shared between subscriptions and as such * should be thread-safe.

    @@ -3314,7 +3314,7 @@ public final Flowable flattenAsFlowable(@NonNull Function - * + * *
    *
    Scheduler:
    *
    {@code flatMapObservable} does not operate by default on a particular {@link Scheduler}.
    @@ -3687,7 +3687,7 @@ public final Single> materialize() { * Signals {@code true} if the current {@code Single} signals a success value that is {@link Object#equals(Object)} with the value * provided. *

    - * + * *

    * *

    @@ -3734,7 +3734,7 @@ public final Single contains(@NonNull Object item, @NonNull BiPredicate /** * Flattens this {@code Single} and another {@link SingleSource} into one {@link Flowable}, without any transformation. *

    - * + * *

    * You can combine items emitted by multiple {@code SingleSource}s so that they appear as one {@code Flowable}, by using * the {@code mergeWith} method. @@ -3814,7 +3814,7 @@ public final Single observeOn(@NonNull Scheduler scheduler) { * Ends the flow with a success item returned by a function for the {@link Throwable} error signaled by the current * {@code Single} instead of signaling the error via {@code onError}. *

    - * + * *

    * By default, when a {@code Single} encounters an error that prevents it from emitting the expected item to its * subscriber, the {@code Single} invokes its subscriber's {@link SingleObserver#onError} method, and then quits @@ -3848,7 +3848,7 @@ public final Single onErrorReturn(@NonNull Function i /** * Signals the specified value as success in case the current {@code Single} signals an error. *

    - * + * *

    *
    Scheduler:
    *
    {@code onErrorReturnItem} does not operate by default on a particular {@link Scheduler}.
    @@ -3870,7 +3870,7 @@ public final Single onErrorReturnItem(@NonNull T item) { * Resumes the flow with the given {@link SingleSource} when the current {@code Single} fails instead of * signaling the error via {@code onError}. *

    - * + * *

    * By default, when a {@code Single} encounters an error that prevents it from emitting the expected item to * its {@link SingleObserver}, the {@code Single} invokes its {@code SingleObserver}'s {@code onError} method, and then quits @@ -3925,7 +3925,7 @@ public final Maybe onErrorComplete() { * Returns a {@link Maybe} instance that if this {@code Single} emits an error and the predicate returns * {@code true}, it will emit an {@code onComplete} and swallow the throwable. *

    - * + * *

    *
    Scheduler:
    *
    {@code onErrorComplete} does not operate by default on a particular {@link Scheduler}.
    @@ -3949,7 +3949,7 @@ public final Maybe onErrorComplete(@NonNull Predicate pred * Resumes the flow with a {@link SingleSource} returned for the failure {@link Throwable} of the current {@code Single} by a * function instead of signaling the error via {@code onError}. *

    - * + * *

    * By default, when a {@code Single} encounters an error that prevents it from emitting the expected item to * its {@link SingleObserver}, the {@code Single} invokes its {@code SingleObserver}'s {@code onError} method, and then quits @@ -4007,7 +4007,7 @@ public final Single onTerminateDetach() { /** * Repeatedly re-subscribes to the current {@code Single} and emits each success value as a {@link Flowable} sequence. *

    - * + * *

    *
    Backpressure:
    *
    The returned {@code Flowable} honors the backpressure of the downstream consumer.
    @@ -4028,7 +4028,7 @@ public final Flowable repeat() { /** * Re-subscribes to the current {@code Single} at most the given number of times and emits each success value as a {@link Flowable} sequence. *

    - * + * *

    *
    Backpressure:
    *
    The returned {@code Flowable} honors the backpressure of the downstream consumer.
    @@ -4053,7 +4053,7 @@ public final Flowable repeat(long times) { * the {@link Publisher} returned by the handler function signals a value in response to a * value signaled through the {@link Flowable} the handler receives. *

    - * + * *

    *
    Backpressure:
    *
    The returned {@code Flowable} honors the backpressure of the downstream consumer. @@ -4946,7 +4946,7 @@ public final Single takeUntil(@NonNull SingleSource other) { * Signals a {@link TimeoutException} if the current {@code Single} doesn't signal a success value within the * specified timeout window. *

    - * + * *

    *
    Scheduler:
    *
    {@code timeout} signals the {@code TimeoutException} on the {@code computation} {@link Scheduler}.
    @@ -5423,7 +5423,7 @@ public final Flowable flattenStreamAsFlowable(@NonNull Function - * + * *

    * The operator closes the {@code Stream} upon cancellation and when it terminates. The exceptions raised when * closing a {@code Stream} are routed to the global error handler ({@link RxJavaPlugins#onError(Throwable)}. diff --git a/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowable.java b/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowable.java index 403f69b1a0..58152e2400 100644 --- a/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowable.java +++ b/src/main/java/io/reactivex/rxjava3/parallel/ParallelFlowable.java @@ -1394,7 +1394,7 @@ public final ParallelFlowable concatMapDelayError( * Returns a {@code ParallelFlowable} that merges each item emitted by the source on each rail with the values in an * {@link Iterable} corresponding to that item that is generated by a selector. *

    - * + * *

    *
    Backpressure:
    *
    The operator honors backpressure from each downstream rail. The source {@code ParallelFlowable}s is @@ -1427,7 +1427,7 @@ public final ParallelFlowable flatMapIterable(@NonNull Function - * + * *
    *
    Backpressure:
    *
    The operator honors backpressure from each downstream rail. The source {@code ParallelFlowable}s is diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java b/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java new file mode 100644 index 0000000000..5c0886ea9d --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ +package io.reactivex.rxjava3.internal.util; + +import java.awt.image.BufferedImage; +import java.io.*; +import java.net.URL; +import java.nio.file.Files; +import java.util.*; +import java.util.regex.*; + +import javax.imageio.ImageIO; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.parallel.ParallelFlowable; +import io.reactivex.rxjava3.testsupport.TestHelper; + +/** + * Parses the main sources, locates the {@code } tags, downloads + * the referenced image and checks if the scaled dimensions are correct. + */ +public final class MarbleDimensions { + + /** Helper program. */ + private MarbleDimensions() { + throw new IllegalStateException("No instances!"); + } + + public static void main(String[] args) throws Throwable { + Pattern p = Pattern.compile("\\s*\\*\\s*\\ dimensions = new HashMap<>(); + + for (Class clazz : CLASSES) { + String simpleName = clazz.getSimpleName(); + System.out.println(simpleName); + System.out.println("----"); + String packageName = clazz.getPackage().getName(); + + File f = TestHelper.findSource(clazz.getSimpleName(), packageName); + if (f == null) { + System.err.println("Unable to locate " + clazz); + continue; + } + + List lines = Files.readAllLines(f.toPath()); + + for (int i = 0; i < lines.size(); i++) { + Matcher m = p.matcher(lines.get(i)); + if (m.matches()) { + int width = Integer.parseInt(m.group(2)); + int height = Integer.parseInt(m.group(5)); + String url = m.group(8); + + Integer[] imageDim = dimensions.get(url); + if (imageDim == null) { + Thread.sleep(SLEEP_PER_IMAGE_MILLIS); + + try { + BufferedImage bimg = ImageIO.read(new URL(url)); + + if (bimg == null) { + throw new IOException("not found"); + } + imageDim = new Integer[] { 0, 0 }; + imageDim[0] = bimg.getWidth(); + imageDim[1] = bimg.getHeight(); + + dimensions.put(url, imageDim); + } catch (IOException ex) { + System.err.printf("%s => %s%n", url, ex); + System.err.printf(" at %s.%s.method(%s.java:%d)%n", packageName, simpleName, simpleName, i + 1); + } + } + + if (imageDim != null) { + int expectedHeight = (int)Math.round(1.0 * width / imageDim[0] * imageDim[1]); + + if (expectedHeight != height) { + System.out.printf(" %d => %d%n", height, expectedHeight); + System.out.printf(" at %s.%s.method(%s.java:%d)%n", packageName, simpleName, simpleName, i + 1); + } + } + // System.out.printf("%d: %d x %d => %s%n", i + 1, width, height, url); + } + } + } + } + + static final int SLEEP_PER_IMAGE_MILLIS = 100; + + static final Class[] CLASSES = { + Flowable.class, Observable.class, Maybe.class, Single.class, Completable.class, ParallelFlowable.class + }; +} From f1a795da0d4cdfb3133206ad8e3887bdb8ba948b Mon Sep 17 00:00:00 2001 From: slisaasquatch Date: Tue, 28 Jan 2020 12:32:19 -0800 Subject: [PATCH 33/37] 3.x: Swap Maybe.flatMapSingle and Maybe.flatMapSingleElement (#6891) * Deleted Maybe.flatMapSingle And replaced tests with flatMapSingle().toSingle() * Renamed Maybe.flatMapSingleElement to flatMapSingle * Deleted unused MaybeFlatMapSingle operator * Renamed operator MaybeFlatMapSingleElement to MaybeFlatMapSingle * Add Ignore to XFlatMapTest.maybeSingle --- .../java/io/reactivex/rxjava3/core/Maybe.java | 37 +---- .../operators/maybe/MaybeFlatMapSingle.java | 21 ++- .../maybe/MaybeFlatMapSingleElement.java | 132 ------------------ .../reactivex/rxjava3/core/XFlatMapTest.java | 2 + .../maybe/MaybeFlatMapSingleElementTest.java | 30 ++-- .../maybe/MaybeFlatMapSingleTest.java | 11 +- 6 files changed, 41 insertions(+), 192 deletions(-) delete mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElement.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 37ce1e99e2..f8cbdcdbe7 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -2932,7 +2932,7 @@ public final Completable concatMapCompletable(@NonNull Function * *

    - * This operator is an alias for {@link #flatMapSingleElement(Function)}. + * This operator is an alias for {@link #flatMapSingle(Function)}. *

    *
    Scheduler:
    *
    {@code concatMapSingle} does not operate by default on a particular {@link Scheduler}.
    @@ -2951,7 +2951,7 @@ public final Completable concatMapCompletable(@NonNull Function Maybe concatMapSingle(@NonNull Function> mapper) { - return flatMapSingleElement(mapper); + return flatMapSingle(mapper); } /** @@ -3832,33 +3832,6 @@ public final Flowable flatMapPublisher(@NonNull Function(this, mapper)); } - /** - * Returns a {@link Single} based on applying a specified function to the item emitted by the - * current {@code Maybe}, where that function returns a {@code Single}. - * When this {@code Maybe} completes a {@link NoSuchElementException} will be thrown. - *

    - * - *

    - *
    Scheduler:
    - *
    {@code flatMapSingle} does not operate by default on a particular {@link Scheduler}.
    - *
    - * - * @param the result value type - * @param mapper - * a function that, when applied to the item emitted by the current {@code Maybe}, returns a - * {@code Single} - * @return the new {@code Single} instance - * @throws NullPointerException if {@code mapper} is {@code null} - * @see ReactiveX operators documentation: FlatMap - */ - @CheckReturnValue - @NonNull - @SchedulerSupport(SchedulerSupport.NONE) - public final Single flatMapSingle(@NonNull Function> mapper) { - Objects.requireNonNull(mapper, "mapper is null"); - return RxJavaPlugins.onAssembly(new MaybeFlatMapSingle<>(this, mapper)); - } - /** * Returns a {@code Maybe} based on applying a specified function to the item emitted by the * current {@code Maybe}, where that function returns a {@link Single}. @@ -3867,7 +3840,7 @@ public final Single flatMapSingle(@NonNull Function *
    *
    Scheduler:
    - *
    {@code flatMapSingleElement} does not operate by default on a particular {@link Scheduler}.
    + *
    {@code flatMapSingle} does not operate by default on a particular {@link Scheduler}.
    *
    * *

    History: 2.0.2 - experimental @@ -3883,9 +3856,9 @@ public final Single flatMapSingle(@NonNull Function Maybe flatMapSingleElement(@NonNull Function> mapper) { + public final Maybe flatMapSingle(@NonNull Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); - return RxJavaPlugins.onAssembly(new MaybeFlatMapSingleElement<>(this, mapper)); + return RxJavaPlugins.onAssembly(new MaybeFlatMapSingle<>(this, mapper)); } /** diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java index 2199ea470b..aed71dc855 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java @@ -13,7 +13,6 @@ package io.reactivex.rxjava3.internal.operators.maybe; -import java.util.NoSuchElementException; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; @@ -25,10 +24,12 @@ /** * Maps the success value of the source MaybeSource into a Single. + *

    History: 2.0.2 - experimental * @param the input value type * @param the result value type + * @since 2.1 */ -public final class MaybeFlatMapSingle extends Single { +public final class MaybeFlatMapSingle extends Maybe { final MaybeSource source; @@ -40,7 +41,7 @@ public MaybeFlatMapSingle(MaybeSource source, Function downstream) { + protected void subscribeActual(MaybeObserver downstream) { source.subscribe(new FlatMapMaybeObserver<>(downstream, mapper)); } @@ -50,11 +51,11 @@ static final class FlatMapMaybeObserver private static final long serialVersionUID = 4827726964688405508L; - final SingleObserver downstream; + final MaybeObserver downstream; final Function> mapper; - FlatMapMaybeObserver(SingleObserver actual, Function> mapper) { + FlatMapMaybeObserver(MaybeObserver actual, Function> mapper) { this.downstream = actual; this.mapper = mapper; } @@ -88,9 +89,7 @@ public void onSuccess(T value) { return; } - if (!isDisposed()) { - ss.subscribe(new FlatMapSingleObserver(this, downstream)); - } + ss.subscribe(new FlatMapSingleObserver(this, downstream)); } @Override @@ -100,7 +99,7 @@ public void onError(Throwable e) { @Override public void onComplete() { - downstream.onError(new NoSuchElementException()); + downstream.onComplete(); } } @@ -108,9 +107,9 @@ static final class FlatMapSingleObserver implements SingleObserver { final AtomicReference parent; - final SingleObserver downstream; + final MaybeObserver downstream; - FlatMapSingleObserver(AtomicReference parent, SingleObserver downstream) { + FlatMapSingleObserver(AtomicReference parent, MaybeObserver downstream) { this.parent = parent; this.downstream = downstream; } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElement.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElement.java deleted file mode 100644 index 49b7100575..0000000000 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElement.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Copyright (c) 2016-present, RxJava Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is - * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See - * the License for the specific language governing permissions and limitations under the License. - */ - -package io.reactivex.rxjava3.internal.operators.maybe; - -import java.util.Objects; -import java.util.concurrent.atomic.AtomicReference; - -import io.reactivex.rxjava3.core.*; -import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.exceptions.Exceptions; -import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.internal.disposables.DisposableHelper; - -/** - * Maps the success value of the source MaybeSource into a Single. - *

    History: 2.0.2 - experimental - * @param the input value type - * @param the result value type - * @since 2.1 - */ -public final class MaybeFlatMapSingleElement extends Maybe { - - final MaybeSource source; - - final Function> mapper; - - public MaybeFlatMapSingleElement(MaybeSource source, Function> mapper) { - this.source = source; - this.mapper = mapper; - } - - @Override - protected void subscribeActual(MaybeObserver downstream) { - source.subscribe(new FlatMapMaybeObserver<>(downstream, mapper)); - } - - static final class FlatMapMaybeObserver - extends AtomicReference - implements MaybeObserver, Disposable { - - private static final long serialVersionUID = 4827726964688405508L; - - final MaybeObserver downstream; - - final Function> mapper; - - FlatMapMaybeObserver(MaybeObserver actual, Function> mapper) { - this.downstream = actual; - this.mapper = mapper; - } - - @Override - public void dispose() { - DisposableHelper.dispose(this); - } - - @Override - public boolean isDisposed() { - return DisposableHelper.isDisposed(get()); - } - - @Override - public void onSubscribe(Disposable d) { - if (DisposableHelper.setOnce(this, d)) { - downstream.onSubscribe(this); - } - } - - @Override - public void onSuccess(T value) { - SingleSource ss; - - try { - ss = Objects.requireNonNull(mapper.apply(value), "The mapper returned a null SingleSource"); - } catch (Throwable ex) { - Exceptions.throwIfFatal(ex); - onError(ex); - return; - } - - ss.subscribe(new FlatMapSingleObserver(this, downstream)); - } - - @Override - public void onError(Throwable e) { - downstream.onError(e); - } - - @Override - public void onComplete() { - downstream.onComplete(); - } - } - - static final class FlatMapSingleObserver implements SingleObserver { - - final AtomicReference parent; - - final MaybeObserver downstream; - - FlatMapSingleObserver(AtomicReference parent, MaybeObserver downstream) { - this.parent = parent; - this.downstream = downstream; - } - - @Override - public void onSubscribe(final Disposable d) { - DisposableHelper.replace(parent, d); - } - - @Override - public void onSuccess(final R value) { - downstream.onSuccess(value); - } - - @Override - public void onError(final Throwable e) { - downstream.onError(e); - } - } -} diff --git a/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java b/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java index 7efeee401d..6e80b57904 100644 --- a/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java @@ -505,6 +505,7 @@ public Completable apply(Integer v) throws Exception { } @Test + @Ignore public void maybeSingle() throws Exception { List errors = TestHelper.trackPluginErrors(); try { @@ -517,6 +518,7 @@ public Single apply(Integer v) throws Exception { return Single.error(new TestException()); } }) + .toSingle() .test(); cb.await(); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElementTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElementTest.java index 3d85785add..cc92e023ab 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElementTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleElementTest.java @@ -22,8 +22,8 @@ public class MaybeFlatMapSingleElementTest extends RxJavaTest { @Test - public void flatMapSingleElementValue() { - Maybe.just(1).flatMapSingleElement(new Function>() { + public void flatMapSingleValue() { + Maybe.just(1).flatMapSingle(new Function>() { @Override public SingleSource apply(final Integer integer) throws Exception { if (integer == 1) { return Single.just(2); @@ -37,8 +37,8 @@ public void flatMapSingleElementValue() { } @Test - public void flatMapSingleElementValueDifferentType() { - Maybe.just(1).flatMapSingleElement(new Function>() { + public void flatMapSingleValueDifferentType() { + Maybe.just(1).flatMapSingle(new Function>() { @Override public SingleSource apply(final Integer integer) throws Exception { if (integer == 1) { return Single.just("2"); @@ -52,8 +52,8 @@ public void flatMapSingleElementValueDifferentType() { } @Test - public void flatMapSingleElementValueNull() { - Maybe.just(1).flatMapSingleElement(new Function>() { + public void flatMapSingleValueNull() { + Maybe.just(1).flatMapSingle(new Function>() { @Override public SingleSource apply(final Integer integer) throws Exception { return null; } @@ -65,8 +65,8 @@ public void flatMapSingleElementValueNull() { } @Test - public void flatMapSingleElementValueErrorThrown() { - Maybe.just(1).flatMapSingleElement(new Function>() { + public void flatMapSingleValueErrorThrown() { + Maybe.just(1).flatMapSingle(new Function>() { @Override public SingleSource apply(final Integer integer) throws Exception { throw new RuntimeException("something went terribly wrong!"); } @@ -78,10 +78,10 @@ public void flatMapSingleElementValueErrorThrown() { } @Test - public void flatMapSingleElementError() { + public void flatMapSingleError() { RuntimeException exception = new RuntimeException("test"); - Maybe.error(exception).flatMapSingleElement(new Function>() { + Maybe.error(exception).flatMapSingle(new Function>() { @Override public SingleSource apply(final Object integer) throws Exception { return Single.just(new Object()); } @@ -91,8 +91,8 @@ public void flatMapSingleElementError() { } @Test - public void flatMapSingleElementEmpty() { - Maybe.empty().flatMapSingleElement(new Function>() { + public void flatMapSingleEmpty() { + Maybe.empty().flatMapSingle(new Function>() { @Override public SingleSource apply(final Integer integer) throws Exception { return Single.just(2); } @@ -104,7 +104,7 @@ public void flatMapSingleElementEmpty() { @Test public void dispose() { - TestHelper.checkDisposed(Maybe.just(1).flatMapSingleElement(new Function>() { + TestHelper.checkDisposed(Maybe.just(1).flatMapSingle(new Function>() { @Override public SingleSource apply(final Integer integer) throws Exception { return Single.just(2); @@ -117,7 +117,7 @@ public void doubleOnSubscribe() { TestHelper.checkDoubleOnSubscribeMaybe(new Function, Maybe>() { @Override public Maybe apply(Maybe m) throws Exception { - return m.flatMapSingleElement(new Function>() { + return m.flatMapSingle(new Function>() { @Override public SingleSource apply(final Integer integer) throws Exception { return Single.just(2); @@ -130,7 +130,7 @@ public SingleSource apply(final Integer integer) throws Exception { @Test public void singleErrors() { Maybe.just(1) - .flatMapSingleElement(new Function>() { + .flatMapSingle(new Function>() { @Override public SingleSource apply(final Integer integer) throws Exception { return Single.error(new TestException()); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleTest.java index c4cef0d351..4904678a61 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingleTest.java @@ -34,6 +34,7 @@ public void flatMapSingleValue() { return Single.just(1); } }) + .toSingle() .test() .assertResult(2); } @@ -49,6 +50,7 @@ public void flatMapSingleValueDifferentType() { return Single.just("1"); } }) + .toSingle() .test() .assertResult("2"); } @@ -60,6 +62,7 @@ public void flatMapSingleValueNull() { return null; } }) + .toSingle() .to(TestHelper.testConsumer()) .assertNoValues() .assertError(NullPointerException.class) @@ -73,6 +76,7 @@ public void flatMapSingleValueErrorThrown() { throw new RuntimeException("something went terribly wrong!"); } }) + .toSingle() .to(TestHelper.testConsumer()) .assertNoValues() .assertError(RuntimeException.class) @@ -88,6 +92,7 @@ public void flatMapSingleError() { return Single.just(new Object()); } }) + .toSingle() .test() .assertError(exception); } @@ -99,6 +104,7 @@ public void flatMapSingleEmpty() { return Single.just(2); } }) + .toSingle() .test() .assertNoValues() .assertError(NoSuchElementException.class); @@ -111,7 +117,7 @@ public void dispose() { public SingleSource apply(final Integer integer) throws Exception { return Single.just(2); } - })); + }).toSingle()); } @Test @@ -124,7 +130,7 @@ public SingleSource apply(Maybe m) throws Exception { public SingleSource apply(final Integer integer) throws Exception { return Single.just(2); } - }); + }).toSingle(); } }); } @@ -138,6 +144,7 @@ public SingleSource apply(final Integer integer) throws Exception { return Single.error(new TestException()); } }) + .toSingle() .test() .assertFailure(TestException.class); } From 5f6aafcbaa97f330ad2007f4ad02c5e33db8914b Mon Sep 17 00:00:00 2001 From: David Karnok Date: Wed, 29 Jan 2020 11:57:40 +0100 Subject: [PATCH 34/37] 3.x: Fix groupBy not requesting more if a group is cancelled w/ items (#6895) --- .../operators/flowable/FlowableGroupBy.java | 1 + .../flowable/FlowableGroupByTest.java | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupBy.java b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupBy.java index 3cb84d4d6b..9a42e927bc 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupBy.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupBy.java @@ -401,6 +401,7 @@ public void request(long n) { public void cancel() { if (cancelled.compareAndSet(false, true)) { cancelParent(); + drain(); } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupByTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupByTest.java index f20f0ae0c7..ddc34f1d98 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupByTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableGroupByTest.java @@ -2444,4 +2444,38 @@ public void accept(Integer v) throws Throwable { .assertNoErrors() .assertComplete(); } + + @Test + public void cancelledGroupResumesRequesting() { + final List> tss = new ArrayList<>(); + final AtomicInteger counter = new AtomicInteger(); + final AtomicBoolean done = new AtomicBoolean(); + Flowable.range(1, 1000) + .doOnNext(new Consumer() { + @Override + public void accept(Integer v) throws Exception { + counter.getAndIncrement(); + } + }) + .groupBy(Functions.justFunction(1)) + .subscribe(new Consumer>() { + @Override + public void accept(GroupedFlowable v) throws Exception { + TestSubscriber ts = TestSubscriber.create(0L); + tss.add(ts); + v.subscribe(ts); + } + }, Functions.emptyConsumer(), new Action() { + @Override + public void run() throws Exception { + done.set(true); + } + }); + + while (!done.get()) { + tss.remove(0).cancel(); + } + + assertEquals(1000, counter.get()); + } } From c181169bf238a841c54e8957055ca31c02fd495d Mon Sep 17 00:00:00 2001 From: David Karnok Date: Wed, 29 Jan 2020 12:52:12 +0100 Subject: [PATCH 35/37] 3.x: Reenable XFlatMapTest.maybeSingle, add missing Single operators (#6893) --- .../java/io/reactivex/rxjava3/core/Maybe.java | 4 +- .../io/reactivex/rxjava3/core/Single.java | 66 +++ .../maybe/MaybeFlatMapNotification.java | 12 +- .../operators/maybe/MaybeFlatMapSingle.java | 4 +- .../mixed/MaybeFlatMapObservable.java | 4 +- .../mixed/MaybeFlatMapPublisher.java | 4 +- .../mixed/SingleFlatMapObservable.java | 4 +- .../single/SingleFlatMapBiSelector.java | 156 ++++++ .../single/SingleFlatMapNotification.java | 147 ++++++ .../single/SingleFlatMapPublisher.java | 4 +- .../reactivex/rxjava3/core/XFlatMapTest.java | 443 +++++++++++++++++- .../single/SingleFlatMapBiSelectorTest.java | 205 ++++++++ .../single/SingleFlatMapNotificationTest.java | 113 +++++ 13 files changed, 1153 insertions(+), 13 deletions(-) create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelector.java create mode 100644 src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotification.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelectorTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotificationTest.java diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index f8cbdcdbe7..20e52f2f5f 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -3653,7 +3653,7 @@ public final Maybe flatMap(@NonNull Function * @@ -3691,7 +3691,7 @@ public final Maybe flatMap( * Returns a {@code Maybe} that emits the results of a specified function to the pair of values emitted by the * current {@code Maybe} and a specified mapped {@link MaybeSource}. *

    - * + * *

    *
    Scheduler:
    *
    {@code flatMap} does not operate by default on a particular {@link Scheduler}.
    diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index cab4d3c073..667125b08b 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -3196,6 +3196,72 @@ public final Single flatMap(@NonNull Function(this, mapper)); } + /** + * Returns a {@code Single} that emits the results of a specified function to the pair of values emitted by the + * current {@code Single} and a specified mapped {@link SingleSource}. + *

    + * + *

    + *
    Scheduler:
    + *
    {@code flatMap} does not operate by default on a particular {@link Scheduler}.
    + *
    + * + * @param + * the type of items emitted by the {@code SingleSource} returned by the {@code mapper} function + * @param + * the type of items emitted by the resulting {@code Single} + * @param mapper + * a function that returns a {@code SingleSource} for the item emitted by the current {@code Single} + * @param combiner + * a function that combines one item emitted by each of the source and collection {@code SingleSource} and + * returns an item to be emitted by the resulting {@code SingleSource} + * @return the new {@code Single} instance + * @throws NullPointerException if {@code mapper} or {@code combiner} is {@code null} + * @see ReactiveX operators documentation: FlatMap + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Single flatMap(@NonNull Function> mapper, + @NonNull BiFunction combiner) { + Objects.requireNonNull(mapper, "mapper is null"); + Objects.requireNonNull(combiner, "combiner is null"); + return RxJavaPlugins.onAssembly(new SingleFlatMapBiSelector<>(this, mapper, combiner)); + } + + /** + * Maps the {@code onSuccess} or {@code onError} signals of the current {@code Single} into a {@link SingleSource} and emits that + * {@code SingleSource}'s signals. + *

    + * + *

    + *
    Scheduler:
    + *
    {@code flatMap} does not operate by default on a particular {@link Scheduler}.
    + *
    + * + * @param + * the result type + * @param onSuccessMapper + * a function that returns a {@code SingleSource} to merge for the {@code onSuccess} item emitted by this {@code Single} + * @param onErrorMapper + * a function that returns a {@code SingleSource} to merge for an {@code onError} notification from this {@code Single} + * @return the new {@code Single} instance + * @throws NullPointerException if {@code onSuccessMapper} or {@code onErrorMapper} is {@code null} + * @see ReactiveX operators documentation: FlatMap + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public final Single flatMap( + @NonNull Function> onSuccessMapper, + @NonNull Function> onErrorMapper) { + Objects.requireNonNull(onSuccessMapper, "onSuccessMapper is null"); + Objects.requireNonNull(onErrorMapper, "onErrorMapper is null"); + return RxJavaPlugins.onAssembly(new SingleFlatMapNotification<>(this, onSuccessMapper, onErrorMapper)); + } + /** * Returns a {@link Maybe} that is based on applying a specified function to the item emitted by the current {@code Single}, * where that function returns a {@link MaybeSource}. diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotification.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotification.java index e357938db2..ffe6ee5e20 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotification.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapNotification.java @@ -109,7 +109,9 @@ public void onSuccess(T value) { return; } - source.subscribe(new InnerObserver()); + if (!isDisposed()) { + source.subscribe(new InnerObserver()); + } } @Override @@ -124,7 +126,9 @@ public void onError(Throwable e) { return; } - source.subscribe(new InnerObserver()); + if (!isDisposed()) { + source.subscribe(new InnerObserver()); + } } @Override @@ -139,7 +143,9 @@ public void onComplete() { return; } - source.subscribe(new InnerObserver()); + if (!isDisposed()) { + source.subscribe(new InnerObserver()); + } } final class InnerObserver implements MaybeObserver { diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java index aed71dc855..999b22f836 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeFlatMapSingle.java @@ -89,7 +89,9 @@ public void onSuccess(T value) { return; } - ss.subscribe(new FlatMapSingleObserver(this, downstream)); + if (!isDisposed()) { + ss.subscribe(new FlatMapSingleObserver(this, downstream)); + } } @Override diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservable.java index ae42405f74..ef1dc5f023 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapObservable.java @@ -106,7 +106,9 @@ public void onSuccess(T t) { return; } - o.subscribe(this); + if (!isDisposed()) { + o.subscribe(this); + } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisher.java index c590755704..82a6d5da7d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/MaybeFlatMapPublisher.java @@ -116,7 +116,9 @@ public void onSuccess(T t) { return; } - p.subscribe(this); + if (get() != SubscriptionHelper.CANCELLED) { + p.subscribe(this); + } } @Override diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservable.java b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservable.java index c3dd9b59c1..b2562d8dba 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservable.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/mixed/SingleFlatMapObservable.java @@ -106,7 +106,9 @@ public void onSuccess(T t) { return; } - o.subscribe(this); + if (!isDisposed()) { + o.subscribe(this); + } } } diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelector.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelector.java new file mode 100644 index 0000000000..d1051f3357 --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelector.java @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.Exceptions; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; + +/** + * Maps a source item to another SingleSource then calls a BiFunction with the + * original item and the secondary item to generate the final result. + * + * @param the main value type + * @param the second value type + * @param the result value type + * @since 3.0.0 + */ +public final class SingleFlatMapBiSelector extends Single { + + final SingleSource source; + + final Function> mapper; + + final BiFunction resultSelector; + + public SingleFlatMapBiSelector(SingleSource source, + Function> mapper, + BiFunction resultSelector) { + this.source = source; + this.mapper = mapper; + this.resultSelector = resultSelector; + } + + @Override + protected void subscribeActual(SingleObserver observer) { + source.subscribe(new FlatMapBiMainObserver(observer, mapper, resultSelector)); + } + + static final class FlatMapBiMainObserver + implements SingleObserver, Disposable { + + final Function> mapper; + + final InnerObserver inner; + + FlatMapBiMainObserver(SingleObserver actual, + Function> mapper, + BiFunction resultSelector) { + this.inner = new InnerObserver<>(actual, resultSelector); + this.mapper = mapper; + } + + @Override + public void dispose() { + DisposableHelper.dispose(inner); + } + + @Override + public boolean isDisposed() { + return DisposableHelper.isDisposed(inner.get()); + } + + @Override + public void onSubscribe(Disposable d) { + if (DisposableHelper.setOnce(inner, d)) { + inner.downstream.onSubscribe(this); + } + } + + @Override + public void onSuccess(T value) { + SingleSource next; + + try { + next = Objects.requireNonNull(mapper.apply(value), "The mapper returned a null MaybeSource"); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + inner.downstream.onError(ex); + return; + } + + if (DisposableHelper.replace(inner, null)) { + inner.value = value; + next.subscribe(inner); + } + } + + @Override + public void onError(Throwable e) { + inner.downstream.onError(e); + } + + static final class InnerObserver + extends AtomicReference + implements SingleObserver { + + private static final long serialVersionUID = -2897979525538174559L; + + final SingleObserver downstream; + + final BiFunction resultSelector; + + T value; + + InnerObserver(SingleObserver actual, + BiFunction resultSelector) { + this.downstream = actual; + this.resultSelector = resultSelector; + } + + @Override + public void onSubscribe(Disposable d) { + DisposableHelper.setOnce(this, d); + } + + @Override + public void onSuccess(U value) { + T t = this.value; + this.value = null; + + R r; + + try { + r = Objects.requireNonNull(resultSelector.apply(t, value), "The resultSelector returned a null value"); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + downstream.onError(ex); + return; + } + + downstream.onSuccess(r); + } + + @Override + public void onError(Throwable e) { + downstream.onError(e); + } + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotification.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotification.java new file mode 100644 index 0000000000..1ba9796b7c --- /dev/null +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotification.java @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.internal.disposables.DisposableHelper; + +/** + * Maps a value into a SingleSource and relays its signal. + * + * @param the source value type + * @param the result value type + * @since 3.0.0 + */ +public final class SingleFlatMapNotification extends Single { + + final SingleSource source; + + final Function> onSuccessMapper; + + final Function> onErrorMapper; + + public SingleFlatMapNotification(SingleSource source, + Function> onSuccessMapper, + Function> onErrorMapper) { + this.source = source; + this.onSuccessMapper = onSuccessMapper; + this.onErrorMapper = onErrorMapper; + } + + @Override + protected void subscribeActual(SingleObserver observer) { + source.subscribe(new FlatMapSingleObserver<>(observer, onSuccessMapper, onErrorMapper)); + } + + static final class FlatMapSingleObserver + extends AtomicReference + implements SingleObserver, Disposable { + + private static final long serialVersionUID = 4375739915521278546L; + + final SingleObserver downstream; + + final Function> onSuccessMapper; + + final Function> onErrorMapper; + + Disposable upstream; + + FlatMapSingleObserver(SingleObserver actual, + Function> onSuccessMapper, + Function> onErrorMapper) { + this.downstream = actual; + this.onSuccessMapper = onSuccessMapper; + this.onErrorMapper = onErrorMapper; + } + + @Override + public void dispose() { + DisposableHelper.dispose(this); + upstream.dispose(); + } + + @Override + public boolean isDisposed() { + return DisposableHelper.isDisposed(get()); + } + + @Override + public void onSubscribe(Disposable d) { + if (DisposableHelper.validate(this.upstream, d)) { + this.upstream = d; + + downstream.onSubscribe(this); + } + } + + @Override + public void onSuccess(T value) { + SingleSource source; + + try { + source = Objects.requireNonNull(onSuccessMapper.apply(value), "The onSuccessMapper returned a null SingleSource"); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + downstream.onError(ex); + return; + } + + if (!isDisposed()) { + source.subscribe(new InnerObserver()); + } + } + + @Override + public void onError(Throwable e) { + SingleSource source; + + try { + source = Objects.requireNonNull(onErrorMapper.apply(e), "The onErrorMapper returned a null SingleSource"); + } catch (Throwable ex) { + Exceptions.throwIfFatal(ex); + downstream.onError(new CompositeException(e, ex)); + return; + } + + if (!isDisposed()) { + source.subscribe(new InnerObserver()); + } + } + + final class InnerObserver implements SingleObserver { + + @Override + public void onSubscribe(Disposable d) { + DisposableHelper.setOnce(FlatMapSingleObserver.this, d); + } + + @Override + public void onSuccess(R value) { + downstream.onSuccess(value); + } + + @Override + public void onError(Throwable e) { + downstream.onError(e); + } + } + } +} diff --git a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapPublisher.java b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapPublisher.java index f474830e40..c89913791d 100644 --- a/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapPublisher.java +++ b/src/main/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapPublisher.java @@ -92,7 +92,9 @@ public void onSuccess(S value) { downstream.onError(e); return; } - f.subscribe(this); + if (parent.get() != SubscriptionHelper.CANCELLED) { + f.subscribe(this); + } } @Override diff --git a/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java b/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java index 6e80b57904..06394de7ab 100644 --- a/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java +++ b/src/test/java/io/reactivex/rxjava3/core/XFlatMapTest.java @@ -22,7 +22,7 @@ import org.reactivestreams.Publisher; import io.reactivex.rxjava3.exceptions.TestException; -import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.functions.*; import io.reactivex.rxjava3.observers.TestObserver; import io.reactivex.rxjava3.plugins.RxJavaPlugins; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -224,7 +224,7 @@ public Completable apply(Integer v) throws Exception { } @Test - public void observableFlowable() throws Exception { + public void observableObservable() throws Exception { List errors = TestHelper.trackPluginErrors(); try { TestObserver to = Observable.just(1) @@ -505,7 +505,179 @@ public Completable apply(Integer v) throws Exception { } @Test - @Ignore + public void singlePublisher() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestSubscriber ts = Single.just(1) + .subscribeOn(Schedulers.io()) + .flatMapPublisher(new Function>() { + @Override + public Publisher apply(Integer v) throws Exception { + sleep(); + return Flowable.error(new TestException()); + } + }) + .test(); + + cb.await(); + + beforeCancelSleep(ts); + + ts.cancel(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + ts.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void singleCombiner() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestObserver to = Single.just(1) + .subscribeOn(Schedulers.io()) + .flatMap(new Function>() { + @Override + public Single apply(Integer v) throws Exception { + sleep(); + return Single.error(new TestException()); + } + }, (a, b) -> a + b) + .test(); + + cb.await(); + + beforeCancelSleep(to); + + to.dispose(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + to.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void singleObservable() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestObserver to = Single.just(1) + .subscribeOn(Schedulers.io()) + .flatMapObservable(new Function>() { + @Override + public Observable apply(Integer v) throws Exception { + sleep(); + return Observable.error(new TestException()); + } + }) + .test(); + + cb.await(); + + beforeCancelSleep(to); + + to.dispose(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + to.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void singleNotificationSuccess() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestObserver to = Single.just(1) + .subscribeOn(Schedulers.io()) + .flatMap( + new Function>() { + @Override + public Single apply(Integer v) throws Exception { + sleep(); + return Single.error(new TestException()); + } + }, + new Function>() { + @Override + public Single apply(Throwable v) throws Exception { + sleep(); + return Single.error(new TestException()); + } + } + ) + .test(); + + cb.await(); + + beforeCancelSleep(to); + + to.dispose(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + to.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void singleNotificationError() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestObserver to = Single.error(new TestException()) + .subscribeOn(Schedulers.io()) + .flatMap( + new Function>() { + @Override + public Single apply(Integer v) throws Exception { + sleep(); + return Single.error(new TestException()); + } + }, + new Function>() { + @Override + public Single apply(Throwable v) throws Exception { + sleep(); + return Single.error(new TestException()); + } + } + ) + .test(); + + cb.await(); + + beforeCancelSleep(to); + + to.dispose(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + to.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test public void maybeSingle() throws Exception { List errors = TestHelper.trackPluginErrors(); try { @@ -537,6 +709,37 @@ public Single apply(Integer v) throws Exception { } } + @Test + public void maybeSingle2() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestObserver to = Maybe.just(1) + .subscribeOn(Schedulers.io()) + .flatMapSingle(new Function>() { + @Override + public Single apply(Integer v) throws Exception { + sleep(); + return Single.error(new TestException()); + } + }) + .test(); + + cb.await(); + + beforeCancelSleep(to); + + to.dispose(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + to.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + @Test public void maybeMaybe() throws Exception { List errors = TestHelper.trackPluginErrors(); @@ -568,6 +771,240 @@ public Maybe apply(Integer v) throws Exception { } } + @Test + public void maybePublisher() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestSubscriber ts = Maybe.just(1) + .subscribeOn(Schedulers.io()) + .flatMapPublisher(new Function>() { + @Override + public Publisher apply(Integer v) throws Exception { + sleep(); + return Flowable.error(new TestException()); + } + }) + .test(); + + cb.await(); + + beforeCancelSleep(ts); + + ts.cancel(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + ts.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void maybeObservable() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestObserver to = Maybe.just(1) + .subscribeOn(Schedulers.io()) + .flatMapObservable(new Function>() { + @Override + public Observable apply(Integer v) throws Exception { + sleep(); + return Observable.error(new TestException()); + } + }) + .test(); + + cb.await(); + + beforeCancelSleep(to); + + to.dispose(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + to.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void maybeNotificationSuccess() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestObserver to = Maybe.just(1) + .subscribeOn(Schedulers.io()) + .flatMap( + new Function>() { + @Override + public Maybe apply(Integer v) throws Exception { + sleep(); + return Maybe.error(new TestException()); + } + }, + new Function>() { + @Override + public Maybe apply(Throwable v) throws Exception { + sleep(); + return Maybe.error(new TestException()); + } + }, + new Supplier>() { + @Override + public Maybe get() throws Exception { + sleep(); + return Maybe.error(new TestException()); + } + } + ) + .test(); + + cb.await(); + + beforeCancelSleep(to); + + to.dispose(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + to.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void maybeNotificationError() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestObserver to = Maybe.error(new TestException()) + .subscribeOn(Schedulers.io()) + .flatMap( + new Function>() { + @Override + public Maybe apply(Integer v) throws Exception { + sleep(); + return Maybe.error(new TestException()); + } + }, + new Function>() { + @Override + public Maybe apply(Throwable v) throws Exception { + sleep(); + return Maybe.error(new TestException()); + } + }, + new Supplier>() { + @Override + public Maybe get() throws Exception { + sleep(); + return Maybe.error(new TestException()); + } + } + ) + .test(); + + cb.await(); + + beforeCancelSleep(to); + + to.dispose(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + to.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void maybeNotificationEmpty() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestObserver to = Maybe.empty() + .subscribeOn(Schedulers.io()) + .flatMap( + new Function>() { + @Override + public Maybe apply(Integer v) throws Exception { + sleep(); + return Maybe.error(new TestException()); + } + }, + new Function>() { + @Override + public Maybe apply(Throwable v) throws Exception { + sleep(); + return Maybe.error(new TestException()); + } + }, + new Supplier>() { + @Override + public Maybe get() throws Exception { + sleep(); + return Maybe.error(new TestException()); + } + } + ) + .test(); + + cb.await(); + + beforeCancelSleep(to); + + to.dispose(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + to.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void maybeCombiner() throws Exception { + List errors = TestHelper.trackPluginErrors(); + try { + TestObserver to = Maybe.just(1) + .subscribeOn(Schedulers.io()) + .flatMap(new Function>() { + @Override + public Maybe apply(Integer v) throws Exception { + sleep(); + return Maybe.error(new TestException()); + } + }, (a, b) -> a + b) + .test(); + + cb.await(); + + beforeCancelSleep(to); + + to.dispose(); + + Thread.sleep(SLEEP_AFTER_CANCEL); + + to.assertEmpty(); + + assertTrue(errors.toString(), errors.isEmpty()); + } finally { + RxJavaPlugins.reset(); + } + } + @Test public void maybeCompletable() throws Exception { List errors = TestHelper.trackPluginErrors(); diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelectorTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelectorTest.java new file mode 100644 index 0000000000..84a2a650c4 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapBiSelectorTest.java @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; +import io.reactivex.rxjava3.functions.*; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.subjects.SingleSubject; +import io.reactivex.rxjava3.testsupport.TestHelper; + +public class SingleFlatMapBiSelectorTest extends RxJavaTest { + + BiFunction stringCombine() { + return new BiFunction() { + @Override + public String apply(Integer a, Integer b) throws Exception { + return a + ":" + b; + } + }; + } + + @Test + public void normal() { + Single.just(1) + .flatMap(new Function>() { + @Override + public SingleSource apply(Integer v) throws Exception { + return Single.just(2); + } + }, stringCombine()) + .test() + .assertResult("1:2"); + } + + @Test + public void errorWithJust() { + final int[] call = { 0 }; + + Single.error(new TestException()) + .flatMap(new Function>() { + @Override + public SingleSource apply(Integer v) throws Exception { + call[0]++; + return Single.just(1); + } + }, stringCombine()) + .test() + .assertFailure(TestException.class); + + assertEquals(0, call[0]); + } + + @Test + public void justWithError() { + final int[] call = { 0 }; + + Single.just(1) + .flatMap(new Function>() { + @Override + public SingleSource apply(Integer v) throws Exception { + call[0]++; + return Single.error(new TestException()); + } + }, stringCombine()) + .test() + .assertFailure(TestException.class); + + assertEquals(1, call[0]); + } + + @Test + public void dispose() { + TestHelper.checkDisposed(SingleSubject.create() + .flatMap(new Function>() { + @Override + public SingleSource apply(Object v) throws Exception { + return Single.just(1); + } + }, new BiFunction() { + @Override + public Object apply(Object a, Integer b) throws Exception { + return b; + } + })); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeSingle(new Function, SingleSource>() { + @Override + public SingleSource apply(Single v) throws Exception { + return v.flatMap(new Function>() { + @Override + public SingleSource apply(Object v) throws Exception { + return Single.just(1); + } + }, new BiFunction() { + @Override + public Object apply(Object a, Integer b) throws Exception { + return b; + } + }); + } + }); + } + + @Test + public void mapperThrows() { + Single.just(1) + .flatMap(new Function>() { + @Override + public SingleSource apply(Integer v) throws Exception { + throw new TestException(); + } + }, stringCombine()) + .test() + .assertFailure(TestException.class); + } + + @Test + public void mapperReturnsNull() { + Single.just(1) + .flatMap(new Function>() { + @Override + public SingleSource apply(Integer v) throws Exception { + return null; + } + }, stringCombine()) + .test() + .assertFailure(NullPointerException.class); + } + + @Test + public void resultSelectorThrows() { + Single.just(1) + .flatMap(new Function>() { + @Override + public SingleSource apply(Integer v) throws Exception { + return Single.just(2); + } + }, new BiFunction() { + @Override + public Object apply(Integer a, Integer b) throws Exception { + throw new TestException(); + } + }) + .test() + .assertFailure(TestException.class); + } + + @Test + public void resultSelectorReturnsNull() { + Single.just(1) + .flatMap(new Function>() { + @Override + public SingleSource apply(Integer v) throws Exception { + return Single.just(2); + } + }, new BiFunction() { + @Override + public Object apply(Integer a, Integer b) throws Exception { + return null; + } + }) + .test() + .assertFailure(NullPointerException.class); + } + + @Test + public void mapperCancels() { + final TestObserver to = new TestObserver<>(); + + Single.just(1) + .flatMap(new Function>() { + @Override + public SingleSource apply(Integer v) throws Exception { + to.dispose(); + return Single.just(2); + } + }, new BiFunction() { + @Override + public Integer apply(Integer a, Integer b) throws Exception { + throw new IllegalStateException(); + } + }) + .subscribeWith(to) + .assertEmpty(); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotificationTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotificationTest.java new file mode 100644 index 0000000000..266acc93f2 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleFlatMapNotificationTest.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.List; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.*; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.internal.functions.Functions; +import io.reactivex.rxjava3.testsupport.*; + +public class SingleFlatMapNotificationTest extends RxJavaTest { + + @Test + public void dispose() { + TestHelper.checkDisposed(Single.just(1) + .flatMap(Functions.justFunction(Single.just(1)), + Functions.justFunction(Single.just(1)))); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeSingle(new Function, SingleSource>() { + @Override + public SingleSource apply(Single m) throws Exception { + return m + .flatMap(Functions.justFunction(Single.just(1)), + Functions.justFunction(Single.just(1))); + } + }); + } + + @Test + public void onSuccessNull() { + Single.just(1) + .flatMap(Functions.justFunction((Single)null), + Functions.justFunction(Single.just(1))) + .test() + .assertFailure(NullPointerException.class); + } + + @Test + public void onErrorNull() { + TestObserverEx to = Single.error(new TestException()) + .flatMap(Functions.justFunction(Single.just(1)), + Functions.justFunction((Single)null)) + .to(TestHelper.testConsumer()) + .assertFailure(CompositeException.class); + + List ce = TestHelper.compositeList(to.errors().get(0)); + + TestHelper.assertError(ce, 0, TestException.class); + TestHelper.assertError(ce, 1, NullPointerException.class); + } + + @Test + public void onSuccessError() { + Single.just(1) + .flatMap(Functions.justFunction(Single.error(new TestException())), + Functions.justFunction((Single)null)) + .test() + .assertFailure(TestException.class); + } + + @Test + public void onSucccessSuccess() { + Single.just(1) + .flatMap(v -> Single.just(2), e -> Single.just(3)) + .test() + .assertResult(2); + } + + @Test + public void onErrorSuccess() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Single.error(new TestException()) + .flatMap(v -> Single.just(2), e -> Single.just(3)) + .test() + .assertResult(3); + + assertTrue("" + errors, errors.isEmpty()); + }); + } + + @Test + public void onErrorError() throws Throwable { + TestHelper.withErrorTracking(errors -> { + Single.error(new TestException()) + .flatMap(v -> Single.just(2), e -> Single.error(new IOException())) + .test() + .assertFailure(IOException.class); + + assertTrue("" + errors, errors.isEmpty()); + }); + } +} From 7e4bb8b0a076c3b5a4c0c3b2fb559f0ba836c88f Mon Sep 17 00:00:00 2001 From: David Karnok Date: Wed, 29 Jan 2020 18:42:51 +0100 Subject: [PATCH 36/37] 3.x: Add remaining Maybe marbles (+50) (#6897) --- .../java/io/reactivex/rxjava3/core/Maybe.java | 103 ++++++++++++------ 1 file changed, 69 insertions(+), 34 deletions(-) diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 20e52f2f5f..66d5ad143d 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -2602,7 +2602,7 @@ public static Maybe zipArray(@NonNull Function - * + * *
    *
    Scheduler:
    *
    {@code ambWith} does not operate by default on a particular {@link Scheduler}.
    @@ -2626,6 +2626,8 @@ public final Maybe ambWith(@NonNull MaybeSource other) { /** * Waits in a blocking fashion until the current {@code Maybe} signals a success value (which is returned), * {@code null} if completed or an exception (which is propagated). + *

    + * *

    *
    Scheduler:
    *
    {@code blockingGet} does not operate by default on a particular {@link Scheduler}.
    @@ -2648,6 +2650,8 @@ public final T blockingGet() { /** * Waits in a blocking fashion until the current {@code Maybe} signals a success value (which is returned), * defaultValue if completed or an exception (which is propagated). + *

    + * *

    *
    Scheduler:
    *
    {@code blockingGet} does not operate by default on a particular {@link Scheduler}.
    @@ -2803,7 +2807,7 @@ public final void blockingSubscribe(@NonNull MaybeObserver observer) * Returns a {@code Maybe} that subscribes to this {@code Maybe} lazily, caches its event * and replays it, to all the downstream subscribers. *

    - * + * *

    * The operator subscribes only when the first downstream subscriber subscribes and maintains * a single subscription towards this {@code Maybe}. @@ -2849,6 +2853,8 @@ public final Maybe cast(@NonNull Class clazz) { /** * Transform a {@code Maybe} by applying a particular {@link MaybeTransformer} function to it. *

    + * + *

    * This method operates on the {@code Maybe} itself whereas {@link #lift} operates on the {@code Maybe}'s {@link MaybeObserver}s. *

    * If the operator you are creating is designed to act on the individual item emitted by a {@code Maybe}, use @@ -2958,7 +2964,7 @@ public final Maybe concatMapSingle(@NonNull Function - * + * *

    *
    Backpressure:
    *
    The operator honors backpressure from downstream.
    @@ -3009,7 +3015,7 @@ public final Single contains(@NonNull Object item) { * Returns a {@link Single} that counts the total number of items emitted (0 or 1) by the current {@code Maybe} and emits * this count as a 64-bit {@link Long}. *

    - * + * *

    *
    Scheduler:
    *
    {@code count} does not operate by default on a particular {@link Scheduler}.
    @@ -3029,7 +3035,7 @@ public final Single count() { * Returns a {@link Single} that emits the item emitted by the current {@code Maybe} or a specified default item * if the current {@code Maybe} is empty. *

    - * + * *

    *
    Scheduler:
    *
    {@code defaultIfEmpty} does not operate by default on a particular {@link Scheduler}.
    @@ -3095,7 +3101,7 @@ public final Single defaultIfEmpty(@NonNull T defaultItem) { * specified delay. * An error signal will not be delayed. *

    - * + * *

    *
    Scheduler:
    *
    This version of {@code delay} operates by default on the {@code computation} {@link Scheduler}.
    @@ -3121,7 +3127,7 @@ public final Maybe delay(long time, @NonNull TimeUnit unit) { * Returns a {@code Maybe} that signals the events emitted by the current {@code Maybe} shifted forward in time by a * specified delay. *

    - * + * *

    *
    Scheduler:
    *
    This version of {@code delay} operates by default on the {@code computation} {@link Scheduler}.
    @@ -3148,7 +3154,7 @@ public final Maybe delay(long time, @NonNull TimeUnit unit, boolean delayErro * specified delay. * An error signal will not be delayed. *

    - * + * *

    *
    Scheduler:
    *
    you specify the {@link Scheduler} where the non-blocking wait and emission happens
    @@ -3173,7 +3179,7 @@ public final Maybe delay(long time, @NonNull TimeUnit unit, @NonNull Schedule * Returns a {@code Maybe} that signals the events emitted by the current {@code Maybe} shifted forward in time by a * specified delay running on the specified {@link Scheduler}. *

    - * + * *

    *
    Scheduler:
    *
    you specify which {@code Scheduler} this operator will use.
    @@ -3203,7 +3209,7 @@ public final Maybe delay(long time, @NonNull TimeUnit unit, @NonNull Schedule /** * Delays the emission of this {@code Maybe} until the given {@link Publisher} signals an item or completes. *

    - * + * *

    *
    Backpressure:
    *
    The {@code delayIndicator} is consumed in an unbounded manner but is cancelled after @@ -3313,6 +3319,8 @@ public final Maybe delaySubscription(long time, @NonNull TimeUnit unit, @NonN * Calls the specified {@link Consumer} with the success item after this item has been emitted to the downstream. *

    Note that the {@code onAfterSuccess} action is shared between subscriptions and as such * should be thread-safe. + *

    + * *

    *
    Scheduler:
    *
    {@code doAfterSuccess} does not operate by default on a particular {@link Scheduler}.
    @@ -3336,7 +3344,7 @@ public final Maybe doAfterSuccess(@NonNull Consumer onAfterSuccess * {@link MaybeObserver#onComplete onSuccess}, * {@link MaybeObserver#onComplete onComplete} or {@link MaybeObserver#onError onError}. *

    - * + * *

    *
    Scheduler:
    *
    {@code doAfterTerminate} does not operate by default on a particular {@link Scheduler}.
    @@ -3365,7 +3373,10 @@ public final Maybe doAfterTerminate(@NonNull Action onAfterTerminate) { /** * Calls the specified action after this {@code Maybe} signals {@code onSuccess}, {@code onError} or {@code onComplete} or gets disposed by * the downstream. - *

    In case of a race between a terminal event and a dispose call, the provided {@code onFinally} action + *

    + * + *

    + * In case of a race between a terminal event and a dispose call, the provided {@code onFinally} action * is executed once per subscription. *

    Note that the {@code onFinally} action is shared between subscriptions and as such * should be thread-safe. @@ -3390,6 +3401,8 @@ public final Maybe doFinally(@NonNull Action onFinally) { /** * Calls the shared {@link Action} if a {@link MaybeObserver} subscribed to the current {@code Maybe} * disposes the common {@link Disposable} it received via {@code onSubscribe}. + *

    + * *

    *
    Scheduler:
    *
    {@code doOnDispose} does not operate by default on a particular {@link Scheduler}.
    @@ -3524,6 +3537,8 @@ public final Maybe doOnLifecycle(@NonNull Consumer onSubs /** * Calls the shared {@link Consumer} with the {@link Disposable} sent through the {@code onSubscribe} for each * {@link MaybeObserver} that subscribes to the current {@code Maybe}. + *

    + * *

    *
    Scheduler:
    *
    {@code doOnSubscribe} does not operate by default on a particular {@link Scheduler}.
    @@ -3550,7 +3565,7 @@ public final Maybe doOnSubscribe(@NonNull Consumer onSubs * Returns a {@code Maybe} instance that calls the given onTerminate callback * just before this {@code Maybe} completes normally or with an exception. *

    - * + * *

    * This differs from {@code doAfterTerminate} in that this happens before the {@code onComplete} or * {@code onError} notification. @@ -3782,7 +3797,7 @@ public final Observable flattenAsObservable(@NonNull Function - * + * *

    *
    Scheduler:
    *
    {@code flatMapObservable} does not operate by default on a particular {@link Scheduler}.
    @@ -3807,7 +3822,7 @@ public final Observable flatMapObservable(@NonNull Function - * + * *
    *
    Backpressure:
    *
    The returned {@code Flowable} honors the downstream backpressure.
    @@ -3927,7 +3942,7 @@ public final Completable ignoreElement() { /** * Returns a {@link Single} that emits {@code true} if the current {@code Maybe} is empty, otherwise {@code false}. *

    - * + * *

    *
    Scheduler:
    *
    {@code isEmpty} does not operate by default on a particular {@link Scheduler}.
    @@ -4150,7 +4165,7 @@ public final Single> materialize() { /** * Flattens this {@code Maybe} and another {@link MaybeSource} into a single {@link Flowable}, without any transformation. *

    - * + * *

    * You can combine items emitted by multiple {@code Maybe}s so that they appear as a single {@code Flowable}, by * using the {@code mergeWith} method. @@ -4231,6 +4246,8 @@ public final Maybe ofType(@NonNull Class clazz) { /** * Calls the specified converter function during assembly time and returns its resulting value. *

    + * + *

    * This allows fluent conversion to any other type. *

    *
    Scheduler:
    @@ -4252,6 +4269,8 @@ public final R to(@NonNull MaybeConverter converter) { /** * Converts this {@code Maybe} into a backpressure-aware {@link Flowable} instance composing cancellation * through. + *

    + * *

    *
    Backpressure:
    *
    The returned {@code Flowable} honors the backpressure of the downstream.
    @@ -4298,6 +4317,8 @@ public final Future toFuture() { /** * Converts this {@code Maybe} into an {@link Observable} instance composing disposal * through. + *

    + * *

    *
    Scheduler:
    *
    {@code toObservable} does not operate by default on a particular {@link Scheduler}.
    @@ -4318,11 +4339,14 @@ public final Observable toObservable() { /** * Converts this {@code Maybe} into a {@link Single} instance composing disposal * through and turning an empty {@code Maybe} into a signal of {@link NoSuchElementException}. + *

    + * *

    *
    Scheduler:
    *
    {@code toSingle} does not operate by default on a particular {@link Scheduler}.
    *
    * @return the new {@code Single} instance + * @see #defaultIfEmpty(Object) */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @@ -4504,7 +4528,7 @@ public final Maybe onTerminateDetach() { /** * Returns a {@link Flowable} that repeats the sequence of items emitted by the current {@code Maybe} indefinitely. *

    - * + * *

    *
    Backpressure:
    *
    The operator honors downstream backpressure.
    @@ -4527,7 +4551,7 @@ public final Flowable repeat() { * Returns a {@link Flowable} that repeats the sequence of items emitted by the current {@code Maybe} at most * {@code count} times. *

    - * + * *

    *
    Backpressure:
    *
    This operator honors downstream backpressure.
    @@ -4555,7 +4579,7 @@ public final Flowable repeat(long times) { * Returns a {@link Flowable} that repeats the sequence of items emitted by the current {@code Maybe} until * the provided stop function returns {@code true}. *

    - * + * *

    *
    Backpressure:
    *
    This operator honors downstream backpressure.
    @@ -4587,7 +4611,7 @@ public final Flowable repeatUntil(@NonNull BooleanSupplier stop) { * call {@code onComplete} or {@code onError} on the child observer. Otherwise, this operator will * resubscribe to the current {@code Maybe}. *

    - * + * *

    *
    Backpressure:
    *
    The operator honors downstream backpressure and expects the source {@code Publisher} to honor backpressure as well. @@ -4614,7 +4638,7 @@ public final Flowable repeatWhen(@NonNull Function, * Returns a {@code Maybe} that mirrors the current {@code Maybe}, resubscribing to it if it calls {@code onError} * (infinite retry count). *

    - * + * *

    * If the current {@code Maybe} calls {@link MaybeObserver#onError}, this operator will resubscribe to the current * {@code Maybe} rather than propagating the {@code onError} call. @@ -4637,7 +4661,7 @@ public final Maybe retry() { * Returns a {@code Maybe} that mirrors the current {@code Maybe}, resubscribing to it if it calls {@code onError} * and the predicate returns {@code true} for that specific exception and retry count. *

    - * + * *

    *
    Scheduler:
    *
    {@code retry} does not operate by default on a particular {@link Scheduler}.
    @@ -4662,7 +4686,7 @@ public final Maybe retry(@NonNull BiPredicate - * + * *

    * If the current {@code Maybe} calls {@link MaybeObserver#onError}, this operator will resubscribe to the current * {@code Maybe} for a maximum of {@code count} resubscriptions rather than propagating the @@ -4687,7 +4711,8 @@ public final Maybe retry(long times) { /** * Retries at most {@code times} or until the predicate returns {@code false}, whichever happens first. - * + *

    + * *

    *
    Scheduler:
    *
    {@code retry} does not operate by default on a particular {@link Scheduler}.
    @@ -4707,6 +4732,8 @@ public final Maybe retry(long times, @NonNull Predicate pr /** * Retries the current {@code Maybe} if it fails and the predicate returns {@code true}. + *

    + * *

    *
    Scheduler:
    *
    {@code retry} does not operate by default on a particular {@link Scheduler}.
    @@ -4751,7 +4778,7 @@ public final Maybe retryUntil(@NonNull BooleanSupplier stop) { * {@code onComplete} or {@code onError} on the child subscription. Otherwise, this operator will * resubscribe to the current {@code Maybe}. *

    - * + * *

    * Example: * @@ -5167,7 +5194,7 @@ public final Maybe subscribeOn(@NonNull Scheduler scheduler) { * Returns a {@code Maybe} that emits the items emitted by the current {@code Maybe} or the items of an alternate * {@link MaybeSource} if the current {@code Maybe} is empty. *

    - * + * *

    *
    Scheduler:
    *
    {@code switchIfEmpty} does not operate by default on a particular {@link Scheduler}.
    @@ -5190,7 +5217,7 @@ public final Maybe switchIfEmpty(@NonNull MaybeSource other) { * Returns a {@link Single} that emits the items emitted by the current {@code Maybe} or the item of an alternate * {@link SingleSource} if the current {@code Maybe} is empty. *

    - * + * *

    *
    Scheduler:
    *
    {@code switchIfEmpty} does not operate by default on a particular {@link Scheduler}.
    @@ -5214,7 +5241,7 @@ public final Single switchIfEmpty(@NonNull SingleSource other) { * Returns a {@code Maybe} that emits the items emitted by the current {@code Maybe} until a second {@link MaybeSource} * emits an item. *

    - * + * *

    *
    Scheduler:
    *
    {@code takeUntil} does not operate by default on a particular {@link Scheduler}.
    @@ -5241,7 +5268,7 @@ public final Maybe takeUntil(@NonNull MaybeSource other) { * Returns a {@code Maybe} that emits the item emitted by the current {@code Maybe} until a second {@link Publisher} * emits an item. *

    - * + * *

    *
    Backpressure:
    *
    The {@code Publisher} is consumed in an unbounded fashion and is cancelled after the first item @@ -5499,7 +5526,7 @@ public final Maybe> timestamp(@NonNull TimeUnit unit, @NonNull Schedule * item. If the next item isn't emitted within the specified timeout duration starting from its predecessor, * the resulting {@code Maybe} terminates and notifies {@link MaybeObserver}s of a {@link TimeoutException}. *

    - * + * *

    *
    Scheduler:
    *
    This version of {@code timeout} operates by default on the {@code computation} {@link Scheduler}.
    @@ -5525,7 +5552,7 @@ public final Maybe timeout(long timeout, @NonNull TimeUnit unit) { * item. If the next item isn't emitted within the specified timeout duration starting from its predecessor, * the current {@code Maybe} is disposed and resulting {@code Maybe} begins instead to mirror a fallback {@link MaybeSource}. *

    - * + * *

    *
    Scheduler:
    *
    This version of {@code timeout} operates by default on the {@code computation} {@link Scheduler}.
    @@ -5555,7 +5582,7 @@ public final Maybe timeout(long timeout, @NonNull TimeUnit unit, @NonNull May * starting from its predecessor, the current {@code Maybe} is disposed and resulting {@code Maybe} begins instead * to mirror a fallback {@link MaybeSource}. *

    - * + * *

    *
    Scheduler:
    *
    You specify which {@code Scheduler} this operator will use.
    @@ -5587,7 +5614,7 @@ public final Maybe timeout(long timeout, @NonNull TimeUnit unit, @NonNull Sch * specified timeout duration starting from its predecessor, the resulting {@code Maybe} terminates and * notifies {@link MaybeObserver}s of a {@link TimeoutException}. *

    - * + * *

    *
    Scheduler:
    *
    You specify which {@code Scheduler} this operator will use.
    @@ -5613,6 +5640,8 @@ public final Maybe timeout(long timeout, @NonNull TimeUnit unit, @NonNull Sch /** * If the current {@code Maybe} didn't signal an event before the {@code timeoutIndicator} {@link MaybeSource} signals, a * {@link TimeoutException} is signaled instead. + *

    + * *

    *
    Scheduler:
    *
    {@code timeout} does not operate by default on a particular {@link Scheduler}.
    @@ -5635,6 +5664,8 @@ public final Maybe timeout(@NonNull MaybeSource timeoutIndicator) { * If the current {@code Maybe} didn't signal an event before the {@code timeoutIndicator} {@link MaybeSource} signals, * the current {@code Maybe} is disposed and the {@code fallback} {@code MaybeSource} subscribed to * as a continuation. + *

    + * *

    *
    Scheduler:
    *
    {@code timeout} does not operate by default on a particular {@link Scheduler}.
    @@ -5658,6 +5689,8 @@ public final Maybe timeout(@NonNull MaybeSource timeoutIndicator, @Non /** * If the current {@code Maybe} source didn't signal an event before the {@code timeoutIndicator} {@link Publisher} signals, a * {@link TimeoutException} is signaled instead. + *

    + * *

    *
    Backpressure:
    *
    The {@code timeoutIndicator} {@code Publisher} is consumed in an unbounded manner and @@ -5684,6 +5717,8 @@ public final Maybe timeout(@NonNull Publisher timeoutIndicator) { * If the current {@code Maybe} didn't signal an event before the {@code timeoutIndicator} {@link Publisher} signals, * the current {@code Maybe} is disposed and the {@code fallback} {@link MaybeSource} subscribed to * as a continuation. + *

    + * *

    *
    Backpressure:
    *
    The {@code timeoutIndicator} {@code Publisher} is consumed in an unbounded manner and From 81f0569a8b9b7d27059f127b90fd7335118b2ee4 Mon Sep 17 00:00:00 2001 From: David Karnok Date: Thu, 30 Jan 2020 16:14:12 +0100 Subject: [PATCH 37/37] 3.x: Add concatEagerDelayError across (#6899) * 3.x: Add concatEagerDelayError across * Add more since 3.0.0 tags --- docs/Operator-Matrix.md | 258 +++++++++--------- .../reactivex/rxjava3/core/Completable.java | 1 + .../io/reactivex/rxjava3/core/Flowable.java | 171 +++++++++++- .../java/io/reactivex/rxjava3/core/Maybe.java | 206 +++++++++++++- .../io/reactivex/rxjava3/core/Observable.java | 156 +++++++++-- .../io/reactivex/rxjava3/core/Single.java | 252 +++++++++++++++-- .../flowable/FlowableConcatMapEagerTest.java | 46 +++- .../operators/maybe/MaybeConcatEagerTest.java | 152 +++++++++++ .../ObservableConcatMapEagerTest.java | 44 +++ .../single/SingleConcatEagerTest.java | 141 ++++++++++ .../internal/util/MarbleDimensions.java | 2 +- .../validators/ParamValidationNaming.java | 1 + 12 files changed, 1238 insertions(+), 192 deletions(-) create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatEagerTest.java create mode 100644 src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatEagerTest.java diff --git a/docs/Operator-Matrix.md b/docs/Operator-Matrix.md index dfa16162e7..afeb8e4182 100644 --- a/docs/Operator-Matrix.md +++ b/docs/Operator-Matrix.md @@ -37,69 +37,69 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `concatArrayEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([25](#notes-25))| `concatDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `concatEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([26](#notes-26))| -`concatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`concatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`concatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([29](#notes-29))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([30](#notes-30))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapEager`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapEagerDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([33](#notes-33))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([34](#notes-34))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([35](#notes-35))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`concatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| `concatWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `contains`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`count`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))| +`count`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([38](#notes-38))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))| `create`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`debounce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`defaultIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`debounce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`defaultIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))| `defer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `delay`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `delaySubscription`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`dematerialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`distinct`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`distinctUntilChanged`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`doAfterNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`doAfterSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`dematerialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`distinct`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`distinctUntilChanged`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([43](#notes-43))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`doAfterNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([44](#notes-44))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`doAfterSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| `doAfterTerminate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `doFinally`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnCancel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([45](#notes-45))| -`doOnComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnDispose`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`doOnCancel`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([46](#notes-46))| +`doOnComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([47](#notes-47))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnDispose`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([48](#notes-48))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| `doOnError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnEvent`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([49](#notes-49))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| +`doOnEvent`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `doOnLifecycle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([50](#notes-50))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`doOnRequest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))| +`doOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`doOnRequest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| `doOnSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`doOnSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`doOnSuccess`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| `doOnTerminate`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`elementAt`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([53](#notes-53))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`elementAtOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`empty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))| +`elementAt`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([54](#notes-54))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`elementAtOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([56](#notes-56))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([55](#notes-55))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`empty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))| `error`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`filter`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`first`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| -`firstElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`firstOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))| -`firstOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| -`firstStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))| -`flatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([31](#notes-31))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapPublisher`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapSingleElement`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([36](#notes-36))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenStreamAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`flattenStreamAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`filter`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`first`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))| +`firstElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`firstOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))| +`firstOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))| +`firstStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| +`flatMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flatMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flatMapIterable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([32](#notes-32))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flatMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flatMapObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([66](#notes-66))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flatMapPublisher`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([67](#notes-67))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([68](#notes-68))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flatMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([65](#notes-65))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flatMapStream`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([37](#notes-37))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flattenAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flattenAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([69](#notes-69))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flattenStreamAsFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`flattenStreamAsObservable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([70](#notes-70))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| `forEach`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| `forEachWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([71](#notes-71))| `fromAction`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -125,17 +125,17 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `ignoreElements`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([82](#notes-82))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| `interval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))| `intervalRange`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([83](#notes-83))| -`isEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`isEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| `join`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([84](#notes-84))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([80](#notes-80))| `just`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`last`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| -`lastElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`lastOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))| -`lastOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| -`lastStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))| +`last`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))| +`lastElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`lastOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))| +`lastOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))| +`lastStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| `lift`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`map`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`mapOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`map`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`mapOptional`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| `materialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `merge`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `mergeArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -145,9 +145,9 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `never`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `observeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `ofType`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([85](#notes-85))| -`onBackpressureBuffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))| -`onBackpressureDrop`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))| -`onBackpressureLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))| +`onBackpressureBuffer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| +`onBackpressureDrop`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| +`onBackpressureLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| `onErrorComplete`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `onErrorResumeNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `onErrorResumeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -158,7 +158,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `publish`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| `range`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| `rangeLong`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([90](#notes-90))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([74](#notes-74))| -`rebatchRequests`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([51](#notes-51))| +`rebatchRequests`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([52](#notes-52))| `reduce`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))| `reduceWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))| `repeat`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -169,19 +169,19 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `retryUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `retryWhen`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `safeSubscribe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`sample`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| `scan`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))| `scanWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([91](#notes-91))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([92](#notes-92))| `sequenceEqual`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `serialize`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([93](#notes-93))| `share`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([87](#notes-87))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([88](#notes-88))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([89](#notes-89))| -`single`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([57](#notes-57))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| -`singleElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| -`singleOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))| -`singleOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| -`singleStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))| -`skip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| -`skipLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| +`single`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([58](#notes-58))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([42](#notes-42))| +`singleElement`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| +`singleOrError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([61](#notes-61))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([62](#notes-62))| +`singleOrErrorStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([64](#notes-64))| +`singleStage`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([63](#notes-63))| +`skip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))| +`skipLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))| `skipUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([94](#notes-94))| `skipWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| `sorted`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([78](#notes-78))| @@ -193,29 +193,29 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `subscribeOn`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `subscribeWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `switchIfEmpty`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([23](#notes-23))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([99](#notes-99))| -`switchMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| -`switchMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([27](#notes-27))| +`switchMap`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`switchMapCompletable`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`switchMapCompletableDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`switchMapDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`switchMapMaybe`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`switchMapMaybeDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`switchMapSingle`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| +`switchMapSingleDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([100](#notes-100))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([28](#notes-28))| `switchOnNext`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `switchOnNextDelayError`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`take`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| -`takeLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([59](#notes-59))| +`take`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))| +`takeLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([60](#notes-60))| `takeUntil`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `takeWhile`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([95](#notes-95))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([2](#notes-2))| `test`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`throttleFirst`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`throttleLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`throttleLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`throttleWithTimeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([39](#notes-39))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| -`timeInterval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`throttleFirst`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`throttleLast`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`throttleLatest`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`throttleWithTimeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| +`timeInterval`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| `timeout`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `timer`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| -`timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([40](#notes-40))| +`timestamp`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([41](#notes-41))| `to`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toCompletionStage`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([101](#notes-101))|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([101](#notes-101))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| `toFlowable`|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([102](#notes-102))|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)| @@ -237,7 +237,7 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat `zip`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([111](#notes-111))| `zipArray`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([112](#notes-112))| `zipWith`|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![present](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png)|![absent](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) ([113](#notes-113))| -**237 operators** | **215** | **209** | **118** | **107** | **84** | +**237 operators** | **216** | **210** | **118** | **108** | **84** | #### Notes 1 Use [`contains()`](#contains).
    @@ -266,48 +266,48 @@ Operator | ![Flowable](https://raw.github.com/wiki/ReactiveX/RxJava/images/opmat 24 No items to keep ordered. Use [`mergeArray()`](#mergeArray).
    25 No items to keep ordered. Use [`mergeArrayDelayError()`](#mergeArrayDelayError).
    26 No items to keep ordered. Use [`merge()`](#merge).
    -27 Always empty thus no items to map.
    -28 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapCompletable`](#concatMapCompletable).
    -29 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMap`](#concatMap).
    -30 At most one item to map. Use [`concatMap()`](#concatMap).
    -31 At most one item. Use [`flattenAsFlowable`](#flattenAsFlowable) or [`flattenAsObservable`](#flattenAsObservable).
    -32 Use [`concatMap`](#concatMap).
    -33 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapMaybe`](#concatMapMaybe).
    -34 Use [`concatMap()`](#concatMap).
    -35 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapSingle`](#concatMapSingle).
    -36 At most one item. Use [`flattenStreamAsFlowable`](#flattenStreamAsFlowable) or [`flattenStreamAsObservable`](#flattenStreamAsObservable).
    -37 Never empty thus always 1.
    -38 Always empty thus always 0.
    -39 At most one item signaled so no subsequent items to work with.
    -40 Always empty thus no items to work with.
    -41 Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.
    -42 At most one item, always distinct.
    -43 Different terminology. Use [`doAfterSuccess()`](#doAfterSuccess).
    -44 Different terminology. Use [`doAfterNext()`](#doAfterNext).
    -45 Different terminology. Use [`doOnDispose()`](#doOnDispose).
    -46 Always succeeds or fails, there is no `onComplete` signal.
    -47 Different terminology. Use [`doOnCancel()`](#doOnCancel).
    -48 At most one item. Use [`doOnEvent()`](#doOnEvent).
    -49 Use [`doOnEach()`](#doOnEach).
    -50 Different terminology. Use [`doOnSuccess()`](#doOnSuccess).
    -51 Backpressure related and not supported outside `Flowable`.
    -52 Different terminology. Use [`doOnNext()`](#doOnNext).
    -53 At most one item with index 0. Use [`defaultIfEmpty`](#defaultIfEmpty).
    -54 Always one item with index 0.
    -55 At most one item with index 0. Use [`toSingle`](#toSingle).
    -56 Use [`complete()`](#complete).
    -57 At most one item. Use [`defaultIfEmpty`](#defaultIfEmpty).
    -58 Always one item.
    -59 At most one item, would be no-op.
    -60 Always one item, would be no-op.
    -61 Always empty. Use [`andThen()`](#andThen) and [`error()`](#error).
    -62 At most one item. Use [`toCompletionStage()`](#toCompletionStage).
    -63 Always empty. Use [`andThen()`](#andThen), [`error()`](#error) and [`toCompletionStage()`](#toCompletionStage).
    -64 Use [`flatMap()`](#flatMap).
    -65 Not supported. Use [`flatMap`](#flatMap) and [`toFlowable()`](#toFlowable).
    -66 Use [`flatMap`](#flatMap).
    -67 Not supported. Use [`flatMap`](#flatMap) and [`toObservable()`](#toFlowable).
    -68 Use [`flatMapSingle`](#flatMapSingle).
    +27 No items to keep ordered. Use [`mergeDelayError()`](#mergeDelayError).
    +28 Always empty thus no items to map.
    +29 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapCompletable`](#concatMapCompletable).
    +30 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMap`](#concatMap).
    +31 At most one item to map. Use [`concatMap()`](#concatMap).
    +32 At most one item. Use [`flattenAsFlowable`](#flattenAsFlowable) or [`flattenAsObservable`](#flattenAsObservable).
    +33 Use [`concatMap`](#concatMap).
    +34 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapMaybe`](#concatMapMaybe).
    +35 Use [`concatMap()`](#concatMap).
    +36 Either the upstream fails (thus no inner) or the mapped-in source, but never both. Use [`concatMapSingle`](#concatMapSingle).
    +37 At most one item. Use [`flattenStreamAsFlowable`](#flattenStreamAsFlowable) or [`flattenStreamAsObservable`](#flattenStreamAsObservable).
    +38 Never empty thus always 1.
    +39 Always empty thus always 0.
    +40 At most one item signaled so no subsequent items to work with.
    +41 Always empty thus no items to work with.
    +42 Always empty. Use [`andThen()`](#andThen) to chose the follow-up sequence.
    +43 At most one item, always distinct.
    +44 Different terminology. Use [`doAfterSuccess()`](#doAfterSuccess).
    +45 Different terminology. Use [`doAfterNext()`](#doAfterNext).
    +46 Different terminology. Use [`doOnDispose()`](#doOnDispose).
    +47 Always succeeds or fails, there is no `onComplete` signal.
    +48 Different terminology. Use [`doOnCancel()`](#doOnCancel).
    +49 At most one item. Use [`doOnEvent()`](#doOnEvent).
    +50 Use [`doOnEach()`](#doOnEach).
    +51 Different terminology. Use [`doOnSuccess()`](#doOnSuccess).
    +52 Backpressure related and not supported outside `Flowable`.
    +53 Different terminology. Use [`doOnNext()`](#doOnNext).
    +54 At most one item with index 0. Use [`defaultIfEmpty`](#defaultIfEmpty).
    +55 Always one item with index 0.
    +56 At most one item with index 0. Use [`toSingle`](#toSingle).
    +57 Use [`complete()`](#complete).
    +58 At most one item. Use [`defaultIfEmpty`](#defaultIfEmpty).
    +59 Always one item.
    +60 At most one item, would be no-op.
    +61 Always one item, would be no-op.
    +62 Always empty. Use [`andThen()`](#andThen) and [`error()`](#error).
    +63 At most one item. Use [`toCompletionStage()`](#toCompletionStage).
    +64 Always empty. Use [`andThen()`](#andThen), [`error()`](#error) and [`toCompletionStage()`](#toCompletionStage).
    +65 Use [`flatMap()`](#flatMap).
    +66 Not supported. Use [`flatMap`](#flatMap) and [`toFlowable()`](#toFlowable).
    +67 Use [`flatMap`](#flatMap).
    +68 Not supported. Use [`flatMap`](#flatMap) and [`toObservable()`](#toFlowable).
    69 Use [`flatMapIterable()`](#flatMapIterable).
    70 Use [`flatMapStream()`](#flatMapStream).
    71 Use [`subscribe()`](#subscribe).
    diff --git a/src/main/java/io/reactivex/rxjava3/core/Completable.java b/src/main/java/io/reactivex/rxjava3/core/Completable.java index cfdd87067d..682a493849 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Completable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Completable.java @@ -1050,6 +1050,7 @@ public static Completable mergeDelayError(@NonNull Publisher<@NonNull ? extends * at a time to the inner {@code CompletableSource}s * @return the new {@code Completable} instance * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} is non-positive */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) diff --git a/src/main/java/io/reactivex/rxjava3/core/Flowable.java b/src/main/java/io/reactivex/rxjava3/core/Flowable.java index 58ffd3d6f8..ddf5b3cf7b 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Flowable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Flowable.java @@ -1648,9 +1648,80 @@ public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? ext return fromPublisher(sources).concatMapDelayError((Function)Functions.identity(), tillTheEnd, prefetch); } + /** + * Concatenates a sequence of {@link Publisher}s eagerly into a single stream of values. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * source {@code Publisher}s. The operator buffers the values emitted by these {@code Publisher}s and then drains them + * in order, each one after the previous one completes. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and the inner {@code Publisher}s are + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code Publisher}s that need to be eagerly concatenated + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 2.0 + */ + @CheckReturnValue + @BackpressureSupport(BackpressureKind.FULL) + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + return concatEager(sources, bufferSize(), bufferSize()); + } + + /** + * Concatenates a sequence of {@link Publisher}s eagerly into a single stream of values and + * runs a limited number of inner sequences at once. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * source {@code Publisher}s. The operator buffers the values emitted by these {@code Publisher}s and then drains them + * in order, each one after the previous one completes. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and both the outer and inner {@code Publisher}s are + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code Publisher}s that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code Publisher}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code Publisher}s can be active at the same time + * @param prefetch the number of elements to prefetch from each inner {@code Publisher} source + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} or {@code prefetch} is non-positive + * @since 2.0 + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.FULL) + @SchedulerSupport(SchedulerSupport.NONE) + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency, int prefetch) { + Objects.requireNonNull(sources, "sources is null"); + ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); + ObjectHelper.verifyPositive(prefetch, "prefetch"); + return RxJavaPlugins.onAssembly(new FlowableConcatMapEager(new FlowableFromIterable(sources), Functions.identity(), maxConcurrency, prefetch, ErrorMode.BOUNDARY)); + } + /** * Concatenates a {@link Publisher} sequence of {@code Publisher}s eagerly into a single stream of values. *

    + * + *

    * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * emitted source {@code Publisher}s as they are observed. The operator buffers the values emitted by these * {@code Publisher}s and then drains them in order, each one after the previous one completes. @@ -1677,7 +1748,10 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends } /** - * Concatenates a {@link Publisher} sequence of {@code Publisher}s eagerly into a single stream of values. + * Concatenates a {@link Publisher} sequence of {@code Publisher}s eagerly into a single stream of values and + * runs a limited number of inner sequences at once. + *

    + * *

    * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * emitted source {@code Publisher}s as they are observed. The operator buffers the values emitted by these @@ -1713,7 +1787,10 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends } /** - * Concatenates a sequence of {@link Publisher}s eagerly into a single stream of values. + * Concatenates a sequence of {@link Publisher}s eagerly into a single stream of values, + * delaying errors until all the inner sequences terminate. + *

    + * *

    * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * source {@code Publisher}s. The operator buffers the values emitted by these {@code Publisher}s and then drains them @@ -1730,18 +1807,22 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends * @param sources a sequence of {@code Publisher}s that need to be eagerly concatenated * @return the new {@code Flowable} instance with the specified concatenation behavior * @throws NullPointerException if {@code sources} is {@code null} - * @since 2.0 + * @since 3.0.0 */ @CheckReturnValue @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { - return concatEager(sources, bufferSize(), bufferSize()); + public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + return concatEagerDelayError(sources, bufferSize(), bufferSize()); } /** - * Concatenates a sequence of {@link Publisher}s eagerly into a single stream of values. + * Concatenates a sequence of {@link Publisher}s eagerly into a single stream of values, + * delaying errors until all the inner sequences terminate and runs a limited number + * of inner sequences at once. + *

    + * *

    * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * source {@code Publisher}s. The operator buffers the values emitted by these {@code Publisher}s and then drains them @@ -1762,18 +1843,89 @@ public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends P * @return the new {@code Flowable} instance with the specified concatenation behavior * @throws NullPointerException if {@code sources} is {@code null} * @throws IllegalArgumentException if {@code maxConcurrency} or {@code prefetch} is non-positive - * @since 2.0 + * @since 3.0.0 */ @CheckReturnValue @NonNull @BackpressureSupport(BackpressureKind.FULL) @SchedulerSupport(SchedulerSupport.NONE) @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency, int prefetch) { + public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency, int prefetch) { Objects.requireNonNull(sources, "sources is null"); ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); ObjectHelper.verifyPositive(prefetch, "prefetch"); - return RxJavaPlugins.onAssembly(new FlowableConcatMapEager(new FlowableFromIterable(sources), Functions.identity(), maxConcurrency, prefetch, ErrorMode.IMMEDIATE)); + return RxJavaPlugins.onAssembly(new FlowableConcatMapEager(new FlowableFromIterable(sources), Functions.identity(), maxConcurrency, prefetch, ErrorMode.END)); + } + + /** + * Concatenates a {@link Publisher} sequence of {@code Publisher}s eagerly into a single stream of values, + * delaying errors until all the inner and the outer sequences terminate. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code Publisher}s as they are observed. The operator buffers the values emitted by these + * {@code Publisher}s and then drains them in order, each one after the previous one completes. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and both the outer and inner {@code Publisher}s are + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code Publisher}s that need to be eagerly concatenated + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @BackpressureSupport(BackpressureKind.FULL) + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources) { + return concatEagerDelayError(sources, bufferSize(), bufferSize()); + } + + /** + * Concatenates a {@link Publisher} sequence of {@code Publisher}s eagerly into a single stream of values, + * delaying errors until all the inner and outer sequences terminate and runs a limited number of inner + * sequences at once. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code Publisher}s as they are observed. The operator buffers the values emitted by these + * {@code Publisher}s and then drains them in order, each one after the previous one completes. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and both the outer and inner {@code Publisher}s are + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code Publisher}s that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code Publisher}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code Publisher}s can be active at the same time + * @param prefetch the number of elements to prefetch from each inner {@code Publisher} source + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} or {@code prefetch} is non-positive + * @since 3.0.0 + */ + @CheckReturnValue + @NonNull + @BackpressureSupport(BackpressureKind.FULL) + @SchedulerSupport(SchedulerSupport.NONE) + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends Publisher<@NonNull ? extends T>> sources, int maxConcurrency, int prefetch) { + Objects.requireNonNull(sources, "sources is null"); + ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency"); + ObjectHelper.verifyPositive(prefetch, "prefetch"); + return RxJavaPlugins.onAssembly(new FlowableConcatMapEagerPublisher(sources, Functions.identity(), maxConcurrency, prefetch, ErrorMode.END)); } /** @@ -10134,6 +10286,7 @@ public final Flowable flatMap(@NonNull FunctionReactiveX operators documentation: FlatMap * @since 2.0 */ diff --git a/src/main/java/io/reactivex/rxjava3/core/Maybe.java b/src/main/java/io/reactivex/rxjava3/core/Maybe.java index 66d5ad143d..784343922d 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Maybe.java +++ b/src/main/java/io/reactivex/rxjava3/core/Maybe.java @@ -561,11 +561,11 @@ public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? ext /** * Concatenates a sequence of {@link MaybeSource}s eagerly into a {@link Flowable} sequence. *

    + * + *

    * Eager concatenation means that once an observer subscribes, this operator subscribes to all of the * source {@code MaybeSource}s. The operator buffers the values emitted by these {@code MaybeSource}s and then drains them * in order, each one after the previous one completes. - *

    - * *

    *
    Backpressure:
    *
    Backpressure is honored towards the downstream.
    @@ -583,7 +583,40 @@ public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? ext @SchedulerSupport(SchedulerSupport.NONE) @NonNull public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { - return Flowable.fromIterable(sources).concatMapEager((Function)MaybeToPublisher.instance()); + return Flowable.fromIterable(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), false); + } + + /** + * Concatenates a sequence of {@link MaybeSource}s eagerly into a {@link Flowable} sequence and + * runs a limited number of the inner sequences at once. + *

    + * + *

    + * Eager concatenation means that once an observer subscribes, this operator subscribes to all of the + * source {@code MaybeSource}s. The operator buffers the values emitted by these {@code MaybeSource}s and then drains them + * in order, each one after the previous one completes. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code MaybeSource} that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code MaybeSource}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code MaybeSource}s can be active at the same time + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} is non-positive + * @since 3.0.0 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { + return Flowable.fromIterable(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), false, maxConcurrency, 1); } /** @@ -616,6 +649,173 @@ public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends return Flowable.fromPublisher(sources).concatMapEager((Function)MaybeToPublisher.instance()); } + /** + * Concatenates a {@link Publisher} sequence of {@link MaybeSource}s eagerly into a {@link Flowable} sequence, + * running at most the given number of inner {@code MaybeSource}s at once. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code MaybeSource}s as they are observed. The operator buffers the values emitted by these + * {@code MaybeSource}s and then drains them in order, each one after the previous one completes. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and the outer {@code Publisher} is + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link io.reactivex.rxjava3.exceptions.MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code MaybeSource}s that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code MaybeSource}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code MaybeSource}s can be active at the same time + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} is non-positive + * @since 3.0.0 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { + return Flowable.fromPublisher(sources).concatMapEager((Function)MaybeToPublisher.instance(), maxConcurrency, 1); + } + + /** + * Concatenates a sequence of {@link MaybeSource}s eagerly into a {@link Flowable} sequence, + * delaying errors until all inner {@code MaybeSource}s terminate. + *

    + * + *

    + * Eager concatenation means that once an observer subscribes, this operator subscribes to all of the + * source {@code MaybeSource}s. The operator buffers the values emitted by these {@code MaybeSource}s and then drains them + * in order, each one after the previous one completes. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code MaybeSource} that need to be eagerly concatenated + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources) { + return Flowable.fromIterable(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), true); + } + + /** + * Concatenates a sequence of {@link MaybeSource}s eagerly into a {@link Flowable} sequence, + * delaying errors until all inner {@code MaybeSource}s terminate and + * runs a limited number of inner {@code MaybeSource}s at once. + *

    + * + *

    + * Eager concatenation means that once an observer subscribes, this operator subscribes to all of the + * source {@code MaybeSource}s. The operator buffers the values emitted by these {@code MaybeSource}s and then drains them + * in order, each one after the previous one completes. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code MaybeSource} that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code MaybeSource}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code MaybeSource}s can be active at the same time + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} is non-positive + * @since 3.0.0 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { + return Flowable.fromIterable(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), true, maxConcurrency, 1); + } + + /** + * Concatenates a {@link Publisher} sequence of {@link MaybeSource}s eagerly into a {@link Flowable} sequence, + * delaying errors until all the inner and the outer sequence terminate. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code MaybeSource}s as they are observed. The operator buffers the values emitted by these + * {@code MaybeSource}s and then drains them in order, each one after the previous one completes. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and the outer {@code Publisher} is + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link io.reactivex.rxjava3.exceptions.MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code MaybeSource}s that need to be eagerly concatenated + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources) { + return Flowable.fromPublisher(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), true); + } + + /** + * Concatenates a {@link Publisher} sequence of {@link MaybeSource}s eagerly into a {@link Flowable} sequence, + * delaying errors until all the inner and the outer sequence terminate and + * runs a limited number of the inner {@code MaybeSource}s at once. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code MaybeSource}s as they are observed. The operator buffers the values emitted by these + * {@code MaybeSource}s and then drains them in order, each one after the previous one completes. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and the outer {@code Publisher} is + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link io.reactivex.rxjava3.exceptions.MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code MaybeSource}s that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code MaybeSource}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code MaybeSource}s can be active at the same time + * @return the new {@code Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} is non-positive + * @since 3.0.0 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends MaybeSource> sources, int maxConcurrency) { + return Flowable.fromPublisher(sources).concatMapEagerDelayError((Function)MaybeToPublisher.instance(), true, maxConcurrency, 1); + } + /** * Provides an API (via a cold {@code Maybe}) that bridges the reactive world with the callback-style world. *

    diff --git a/src/main/java/io/reactivex/rxjava3/core/Observable.java b/src/main/java/io/reactivex/rxjava3/core/Observable.java index 9eeb169871..033d12bdff 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Observable.java +++ b/src/main/java/io/reactivex/rxjava3/core/Observable.java @@ -1460,14 +1460,70 @@ public static Observable concatDelayError(@NonNull ObservableSource + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * {@code ObservableSource}s. The operator buffers the values emitted by these {@code ObservableSource}s and then drains them + * in order, each one after the previous one completes. + *

    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code ObservableSource}s that need to be eagerly concatenated + * @return the new {@code Observable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 2.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Observable concatEager(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { + return concatEager(sources, bufferSize(), bufferSize()); + } + + /** + * Concatenates a sequence of {@link ObservableSource}s eagerly into a single stream of values and + * runs a limited number of inner sequences at once. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * {@code ObservableSource}s. The operator buffers the values emitted by these {@code ObservableSource}s and then drains them + * in order, each one after the previous one completes. + *

    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code ObservableSource}s that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code ObservableSource}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code ObservableSource}s can be active at the same time + * @param bufferSize the number of elements expected from each inner {@code ObservableSource} to be buffered + * @return the new {@code Observable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} or {@code bufferSize} is non-positive + * @since 2.0 + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Observable concatEager(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { + return fromIterable(sources).concatMapEagerDelayError((Function)Functions.identity(), false, maxConcurrency, bufferSize); + } + /** * Concatenates an {@link ObservableSource} sequence of {@code ObservableSource}s eagerly into a single stream of values. *

    + * + *

    * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * emitted source {@code ObservableSource}s as they are observed. The operator buffers the values emitted by these * {@code ObservableSource}s and then drains them in order, each one after the previous one completes. - *

    - * *

    *
    Scheduler:
    *
    This method does not operate by default on a particular {@link Scheduler}.
    @@ -1486,13 +1542,15 @@ public static Observable concatEager(@NonNull ObservableSource + * *

    * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * emitted source {@code ObservableSource}s as they are observed. The operator buffers the values emitted by these * {@code ObservableSource}s and then drains them in order, each one after the previous one completes. - *

    - * *

    *
    Scheduler:
    *
    This method does not operate by default on a particular {@link Scheduler}.
    @@ -1516,13 +1574,14 @@ public static Observable concatEager(@NonNull ObservableSource + * *

    * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * {@code ObservableSource}s. The operator buffers the values emitted by these {@code ObservableSource}s and then drains them * in order, each one after the previous one completes. - *

    - * *

    *
    Scheduler:
    *
    This method does not operate by default on a particular {@link Scheduler}.
    @@ -1531,23 +1590,25 @@ public static Observable concatEager(@NonNull ObservableSource Observable concatEager(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { - return concatEager(sources, bufferSize(), bufferSize()); + public static Observable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources) { + return concatEagerDelayError(sources, bufferSize(), bufferSize()); } /** - * Concatenates a sequence of {@link ObservableSource}s eagerly into a single stream of values. + * Concatenates a sequence of {@link ObservableSource}s eagerly into a single stream of values, + * delaying errors until all the inner sequences terminate and runs a limited number of inner + * sequences at once. + *

    + * *

    * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the * {@code ObservableSource}s. The operator buffers the values emitted by these {@code ObservableSource}s and then drains them * in order, each one after the previous one completes. - *

    - * *

    *
    Scheduler:
    *
    This method does not operate by default on a particular {@link Scheduler}.
    @@ -1560,14 +1621,71 @@ public static Observable concatEager(@NonNull Iterable<@NonNull ? extends * @return the new {@code Observable} instance with the specified concatenation behavior * @throws NullPointerException if {@code sources} is {@code null} * @throws IllegalArgumentException if {@code maxConcurrency} or {@code bufferSize} is non-positive - * @since 2.0 + * @since 3.0.0 */ @SuppressWarnings({ "unchecked", "rawtypes" }) @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) @NonNull - public static Observable concatEager(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { - return fromIterable(sources).concatMapEagerDelayError((Function)Functions.identity(), false, maxConcurrency, bufferSize); + public static Observable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends ObservableSource> sources, int maxConcurrency, int bufferSize) { + return fromIterable(sources).concatMapEagerDelayError((Function)Functions.identity(), true, maxConcurrency, bufferSize); + } + + /** + * Concatenates an {@link ObservableSource} sequence of {@code ObservableSource}s eagerly into a single stream of values, + * delaying errors until all the inner and the outer sequence terminate. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code ObservableSource}s as they are observed. The operator buffers the values emitted by these + * {@code ObservableSource}s and then drains them in order, each one after the previous one completes. + *

    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code ObservableSource}s that need to be eagerly concatenated + * @return the new {@code Observable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Observable concatEagerDelayError(@NonNull ObservableSource> sources) { + return concatEagerDelayError(sources, bufferSize(), bufferSize()); + } + + /** + * Concatenates an {@link ObservableSource} sequence of {@code ObservableSource}s eagerly into a single stream of values, + * delaying errors until all the inner and the outer sequence terminate and runs a limited number of inner sequences at once. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code ObservableSource}s as they are observed. The operator buffers the values emitted by these + * {@code ObservableSource}s and then drains them in order, each one after the previous one completes. + *

    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code ObservableSource}s that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code ObservableSource}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code ObservableSource}s can be active at the same time + * @param bufferSize the number of inner {@code ObservableSource} expected to be buffered + * @return the new {@code Observable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} or {@code bufferSize} is non-positive + * @since 3.0.0 + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + @NonNull + public static Observable concatEagerDelayError(@NonNull ObservableSource> sources, int maxConcurrency, int bufferSize) { + return wrap(sources).concatMapEagerDelayError((Function)Functions.identity(), true, maxConcurrency, bufferSize); } /** @@ -2923,7 +3041,7 @@ public static Observable just(@NonNull T item1, @NonNull T item2, @NonNul * @return the new {@code Observable} instance * @throws NullPointerException if {@code sources} is {@code null} * @throws IllegalArgumentException - * if {@code maxConcurrent} or {@code bufferSize} is non-positive + * if {@code maxConcurrency} or {@code bufferSize} is non-positive * @see ReactiveX operators documentation: Merge * @see #mergeDelayError(Iterable, int, int) */ @@ -2971,7 +3089,7 @@ public static Observable merge(@NonNull Iterable<@NonNull ? extends Obser * @return the new {@code Observable} instance * @throws NullPointerException if {@code sources} is {@code null} * @throws IllegalArgumentException - * if {@code maxConcurrent} or {@code bufferSize} is non-positive + * if {@code maxConcurrency} or {@code bufferSize} is non-positive * @see ReactiveX operators documentation: Merge * @see #mergeArrayDelayError(int, int, ObservableSource...) */ diff --git a/src/main/java/io/reactivex/rxjava3/core/Single.java b/src/main/java/io/reactivex/rxjava3/core/Single.java index 667125b08b..09c67ef5a1 100644 --- a/src/main/java/io/reactivex/rxjava3/core/Single.java +++ b/src/main/java/io/reactivex/rxjava3/core/Single.java @@ -492,35 +492,6 @@ public static Flowable concatArrayEagerDelayError(@NonNull SingleSource - * - *

    - * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the - * emitted source {@code SingleSource}s as they are observed. The operator buffers the values emitted by these - * {@code SingleSource}s and then drains them in order, each one after the previous one succeeds. - *

    - *
    Backpressure:
    - *
    Backpressure is honored towards the downstream and the outer {@code Publisher} is - * expected to support backpressure. Violating this assumption, the operator will - * signal {@link io.reactivex.rxjava3.exceptions.MissingBackpressureException}.
    - *
    Scheduler:
    - *
    This method does not operate by default on a particular {@link Scheduler}.
    - *
    - * @param the value type - * @param sources a sequence of {@code SingleSource}s that need to be eagerly concatenated - * @return the new {@link Flowable} instance with the specified concatenation behavior - * @throws NullPointerException if {@code sources} is {@code null} - */ - @BackpressureSupport(BackpressureKind.FULL) - @CheckReturnValue - @NonNull - @SchedulerSupport(SchedulerSupport.NONE) - public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { - return Flowable.fromPublisher(sources).concatMapEager(SingleInternalHelper.toFlowable()); - } - /** * Concatenates the {@link Iterable} sequence of {@link SingleSource}s into a single sequence by subscribing to each {@code SingleSource}, * one after the other, one at a time and delays any errors till the all inner {@code SingleSource}s terminate @@ -631,7 +602,228 @@ public static Flowable concatDelayError(@NonNull Publisher<@NonNull ? ext @NonNull @SchedulerSupport(SchedulerSupport.NONE) public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { - return Flowable.fromIterable(sources).concatMapEager(SingleInternalHelper.toFlowable()); + return Flowable.fromIterable(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), false); + } + + /** + * Concatenates an {@link Iterable} sequence of {@link SingleSource}s eagerly into a single stream of values and + * runs a limited number of the inner sources at once. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * source {@code SingleSource}s. The operator buffers the values emitted by these {@code SingleSource}s and then drains them + * in order, each one after the previous one succeeds. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources an {@code Iterable} sequence of {@code SingleSource} that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code SingleSource}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code SingleSource}s can be active at the same time + * @return the new {@link Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} is non-positive + * @since 3.0.0 + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Flowable concatEager(@NonNull Iterable<@NonNull ? extends SingleSource> sources, int maxConcurrency) { + return Flowable.fromIterable(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), false, maxConcurrency, 1); + } + + /** + * Concatenates a {@link Publisher} sequence of {@link SingleSource}s eagerly into a single stream of values. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code SingleSource}s as they are observed. The operator buffers the values emitted by these + * {@code SingleSource}s and then drains them in order, each one after the previous one succeeds. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and the outer {@code Publisher} is + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link io.reactivex.rxjava3.exceptions.MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code SingleSource}s that need to be eagerly concatenated + * @return the new {@link Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + return Flowable.fromPublisher(sources).concatMapEager(SingleInternalHelper.toFlowable()); + } + + /** + * Concatenates a {@link Publisher} sequence of {@link SingleSource}s eagerly into a single stream of values and + * runs a limited number of those inner {@code SingleSource}s at once. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code SingleSource}s as they are observed. The operator buffers the values emitted by these + * {@code SingleSource}s and then drains them in order, each one after the previous one succeeds. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and the outer {@code Publisher} is + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link io.reactivex.rxjava3.exceptions.MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code SingleSource}s that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code SingleSource}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code SingleSource}s can be active at the same time + * @return the new {@link Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} is non-positive + * @since 3.0.0 + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Flowable concatEager(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int maxConcurrency) { + return Flowable.fromPublisher(sources).concatMapEager(SingleInternalHelper.toFlowable(), maxConcurrency, 1); + } + + /** + * Concatenates an {@link Iterable} sequence of {@link SingleSource}s eagerly into a single stream of values, + * delaying errors until all the inner sources terminate. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * source {@code SingleSource}s. The operator buffers the values emitted by these {@code SingleSource}s and then drains them + * in order, each one after the previous one succeeds. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources an {@code Iterable} sequence of {@code SingleSource} that need to be eagerly concatenated + * @return the new {@link Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources) { + return Flowable.fromIterable(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), true); + } + + /** + * Concatenates an {@link Iterable} sequence of {@link SingleSource}s eagerly into a single stream of values, + * delaying errors until all the inner sources terminate. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * source {@code SingleSource}s. The operator buffers the values emitted by these {@code SingleSource}s and then drains them + * in order, each one after the previous one succeeds. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources an {@code Iterable} sequence of {@code SingleSource} that need to be eagerly concatenated + * @param maxConcurrency the maximum number of concurrently running inner {@code SingleSource}s; {@link Integer#MAX_VALUE} + * is interpreted as all inner {@code SingleSource}s can be active at the same time + * @return the new {@link Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} is non-positive + * @since 3.0.0 + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Flowable concatEagerDelayError(@NonNull Iterable<@NonNull ? extends SingleSource> sources, int maxConcurrency) { + return Flowable.fromIterable(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), true, maxConcurrency, 1); + } + + /** + * Concatenates a {@link Publisher} sequence of {@link SingleSource}s eagerly into a single stream of values, + * delaying errors until all the inner and the outer sequence terminate. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code SingleSource}s as they are observed. The operator buffers the values emitted by these + * {@code SingleSource}s and then drains them in order, each one after the previous one succeeds. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and the outer {@code Publisher} is + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link io.reactivex.rxjava3.exceptions.MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code SingleSource}s that need to be eagerly concatenated + * @return the new {@link Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @since 3.0.0 + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources) { + return Flowable.fromPublisher(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), true); + } + + /** + * Concatenates a {@link Publisher} sequence of {@link SingleSource}s eagerly into a single stream of values, + * running at most the specified number of those inner {@code SingleSource}s at once and + * delaying errors until all the inner and the outer sequence terminate. + *

    + * + *

    + * Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the + * emitted source {@code SingleSource}s as they are observed. The operator buffers the values emitted by these + * {@code SingleSource}s and then drains them in order, each one after the previous one succeeds. + *

    + *
    Backpressure:
    + *
    Backpressure is honored towards the downstream and the outer {@code Publisher} is + * expected to support backpressure. Violating this assumption, the operator will + * signal {@link io.reactivex.rxjava3.exceptions.MissingBackpressureException}.
    + *
    Scheduler:
    + *
    This method does not operate by default on a particular {@link Scheduler}.
    + *
    + * @param the value type + * @param sources a sequence of {@code SingleSource}s that need to be eagerly concatenated + * @param maxConcurrency the number of inner {@code SingleSource}s to run at once + * @return the new {@link Flowable} instance with the specified concatenation behavior + * @throws NullPointerException if {@code sources} is {@code null} + * @throws IllegalArgumentException if {@code maxConcurrency} is non-positive + * @since 3.0.0 + */ + @BackpressureSupport(BackpressureKind.FULL) + @CheckReturnValue + @NonNull + @SchedulerSupport(SchedulerSupport.NONE) + public static Flowable concatEagerDelayError(@NonNull Publisher<@NonNull ? extends SingleSource> sources, int maxConcurrency) { + return Flowable.fromPublisher(sources).concatMapEagerDelayError(SingleInternalHelper.toFlowable(), true, maxConcurrency, 1); } /** diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerTest.java index 0adfd655b0..b8c2eaaff3 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableConcatMapEagerTest.java @@ -744,7 +744,7 @@ public void Flowable() { } @Test - public void ObservableCapacityHint() { + public void publisherCapacityHint() { Flowable source = Flowable.just(1); TestSubscriber ts = TestSubscriber.create(); @@ -1351,4 +1351,48 @@ public Flowable apply(Integer v) throws Throwable { } }); } + + @Test + public void iterableDelayError() { + Flowable.concatEagerDelayError(Arrays.asList( + Flowable.range(1, 2), + Flowable.error(new TestException()), + Flowable.range(3, 3) + )) + .test() + .assertFailure(TestException.class, 1, 2, 3, 4, 5); + } + + @Test + public void iterableDelayErrorMaxConcurrency() { + Flowable.concatEagerDelayError(Arrays.asList( + Flowable.range(1, 2), + Flowable.error(new TestException()), + Flowable.range(3, 3) + ), 1, 1) + .test() + .assertFailure(TestException.class, 1, 2, 3, 4, 5); + } + + @Test + public void publisherDelayError() { + Flowable.concatEagerDelayError(Flowable.fromArray( + Flowable.range(1, 2), + Flowable.error(new TestException()), + Flowable.range(3, 3) + )) + .test() + .assertFailure(TestException.class, 1, 2, 3, 4, 5); + } + + @Test + public void publisherDelayErrorMaxConcurrency() { + Flowable.concatEagerDelayError(Flowable.fromArray( + Flowable.range(1, 2), + Flowable.error(new TestException()), + Flowable.range(3, 3) + ), 1, 1) + .test() + .assertFailure(TestException.class, 1, 2, 3, 4, 5); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatEagerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatEagerTest.java new file mode 100644 index 0000000000..5a1b42bb15 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeConcatEagerTest.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.maybe; + +import java.util.Arrays; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class MaybeConcatEagerTest { + + @Test + public void iterableNormal() { + Maybe.concatEager(Arrays.asList( + Maybe.just(1), + Maybe.empty(), + Maybe.just(2) + )) + .test() + .assertResult(1, 2); + } + + @Test + public void iterableNormalMaxConcurrency() { + Maybe.concatEager(Arrays.asList( + Maybe.just(1), + Maybe.empty(), + Maybe.just(2) + ), 1) + .test() + .assertResult(1, 2); + } + + @Test + public void iterableError() { + Maybe.concatEager(Arrays.asList( + Maybe.just(1), + Maybe.error(new TestException()), + Maybe.empty(), + Maybe.just(2) + )) + .test() + .assertFailure(TestException.class, 1); + } + + @Test + public void iterableErrorMaxConcurrency() { + Maybe.concatEager(Arrays.asList( + Maybe.just(1), + Maybe.error(new TestException()), + Maybe.empty(), + Maybe.just(2) + ), 1) + .test() + .assertFailure(TestException.class, 1); + } + + @Test + public void publisherNormal() { + Maybe.concatEager(Flowable.fromArray( + Maybe.just(1), + Maybe.empty(), + Maybe.just(2) + )) + .test() + .assertResult(1, 2); + } + + @Test + public void publisherNormalMaxConcurrency() { + Maybe.concatEager(Flowable.fromArray( + Maybe.just(1), + Maybe.empty(), + Maybe.just(2) + ), 1) + .test() + .assertResult(1, 2); + } + + @Test + public void publisherError() { + Maybe.concatEager(Flowable.fromArray( + Maybe.just(1), + Maybe.error(new TestException()), + Maybe.empty(), + Maybe.just(2) + )) + .test() + .assertFailure(TestException.class, 1); + } + + @Test + public void iterableDelayError() { + Maybe.concatEagerDelayError(Arrays.asList( + Maybe.just(1), + Maybe.error(new TestException()), + Maybe.empty(), + Maybe.just(2) + )) + .test() + .assertFailure(TestException.class, 1, 2); + } + + @Test + public void iterableDelayErrorMaxConcurrency() { + Maybe.concatEagerDelayError(Arrays.asList( + Maybe.just(1), + Maybe.error(new TestException()), + Maybe.empty(), + Maybe.just(2) + ), 1) + .test() + .assertFailure(TestException.class, 1, 2); + } + + @Test + public void publisherDelayError() { + Maybe.concatEagerDelayError(Flowable.fromArray( + Maybe.just(1), + Maybe.error(new TestException()), + Maybe.empty(), + Maybe.just(2) + )) + .test() + .assertFailure(TestException.class, 1, 2); + } + + @Test + public void publisherDelayErrorMaxConcurrency() { + Maybe.concatEagerDelayError(Flowable.fromArray( + Maybe.just(1), + Maybe.error(new TestException()), + Maybe.empty(), + Maybe.just(2) + ), 1) + .test() + .assertFailure(TestException.class, 1, 2); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEagerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEagerTest.java index e13124bf5d..054ab91d8f 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEagerTest.java +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableConcatMapEagerTest.java @@ -1034,4 +1034,48 @@ public Observable apply(Integer v) throws Throwable { } }); } + + @Test + public void iterableDelayError() { + Observable.concatEagerDelayError(Arrays.asList( + Observable.range(1, 2), + Observable.error(new TestException()), + Observable.range(3, 3) + )) + .test() + .assertFailure(TestException.class, 1, 2, 3, 4, 5); + } + + @Test + public void iterableDelayErrorMaxConcurrency() { + Observable.concatEagerDelayError(Arrays.asList( + Observable.range(1, 2), + Observable.error(new TestException()), + Observable.range(3, 3) + ), 1, 1) + .test() + .assertFailure(TestException.class, 1, 2, 3, 4, 5); + } + + @Test + public void observerDelayError() { + Observable.concatEagerDelayError(Observable.fromArray( + Observable.range(1, 2), + Observable.error(new TestException()), + Observable.range(3, 3) + )) + .test() + .assertFailure(TestException.class, 1, 2, 3, 4, 5); + } + + @Test + public void observerDelayErrorMaxConcurrency() { + Observable.concatEagerDelayError(Observable.fromArray( + Observable.range(1, 2), + Observable.error(new TestException()), + Observable.range(3, 3) + ), 1, 1) + .test() + .assertFailure(TestException.class, 1, 2, 3, 4, 5); + } } diff --git a/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatEagerTest.java b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatEagerTest.java new file mode 100644 index 0000000000..c21c5347d4 --- /dev/null +++ b/src/test/java/io/reactivex/rxjava3/internal/operators/single/SingleConcatEagerTest.java @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2016-present, RxJava Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the specific language governing permissions and limitations under the License. + */ + +package io.reactivex.rxjava3.internal.operators.single; + +import java.util.Arrays; + +import org.junit.Test; + +import io.reactivex.rxjava3.core.*; +import io.reactivex.rxjava3.exceptions.TestException; + +public class SingleConcatEagerTest { + + @Test + public void iterableNormal() { + Single.concatEager(Arrays.asList( + Single.just(1), + Single.just(2) + )) + .test() + .assertResult(1, 2); + } + + @Test + public void iterableNormalMaxConcurrency() { + Single.concatEager(Arrays.asList( + Single.just(1), + Single.just(2) + ), 1) + .test() + .assertResult(1, 2); + } + + @Test + public void iterableError() { + Single.concatEager(Arrays.asList( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + )) + .test() + .assertFailure(TestException.class, 1); + } + + @Test + public void iterableErrorMaxConcurrency() { + Single.concatEager(Arrays.asList( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + ), 1) + .test() + .assertFailure(TestException.class, 1); + } + + @Test + public void publisherNormal() { + Single.concatEager(Flowable.fromArray( + Single.just(1), + Single.just(2) + )) + .test() + .assertResult(1, 2); + } + + @Test + public void publisherNormalMaxConcurrency() { + Single.concatEager(Flowable.fromArray( + Single.just(1), + Single.just(2) + ), 1) + .test() + .assertResult(1, 2); + } + + @Test + public void publisherError() { + Single.concatEager(Flowable.fromArray( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + )) + .test() + .assertFailure(TestException.class, 1); + } + + @Test + public void iterableDelayError() { + Single.concatEagerDelayError(Arrays.asList( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + )) + .test() + .assertFailure(TestException.class, 1, 2); + } + + @Test + public void iterableDelayErrorMaxConcurrency() { + Single.concatEagerDelayError(Arrays.asList( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + ), 1) + .test() + .assertFailure(TestException.class, 1, 2); + } + + @Test + public void publisherDelayError() { + Single.concatEagerDelayError(Flowable.fromArray( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + )) + .test() + .assertFailure(TestException.class, 1, 2); + } + + @Test + public void publisherDelayErrorMaxConcurrency() { + Single.concatEagerDelayError(Flowable.fromArray( + Single.just(1), + Single.error(new TestException()), + Single.just(2) + ), 1) + .test() + .assertFailure(TestException.class, 1, 2); + } +} diff --git a/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java b/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java index 5c0886ea9d..aa388a684a 100644 --- a/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java +++ b/src/test/java/io/reactivex/rxjava3/internal/util/MarbleDimensions.java @@ -98,7 +98,7 @@ public static void main(String[] args) throws Throwable { } } - static final int SLEEP_PER_IMAGE_MILLIS = 100; + static final int SLEEP_PER_IMAGE_MILLIS = 25; static final Class[] CLASSES = { Flowable.class, Observable.class, Maybe.class, Single.class, Completable.class, ParallelFlowable.class diff --git a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java index 2ce716e342..0445bfbe71 100644 --- a/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java +++ b/src/test/java/io/reactivex/rxjava3/validators/ParamValidationNaming.java @@ -527,6 +527,7 @@ static final class ValidatorStrings { new ValidatorStrings("itemDelayIndicator", "* @throws NullPointerException"), new ValidatorStrings("future", "* @throws NullPointerException"), + new ValidatorStrings("maxConcurrency", "* @throws IllegalArgumentException"), new ValidatorStrings("parallelism", "* @throws IllegalArgumentException"), new ValidatorStrings("prefetch", "* @throws IllegalArgumentException"), new ValidatorStrings("bufferSize", "* @throws IllegalArgumentException"),