From be1bfe658919ee3488c9af8d0b899cbb30c4ee98 Mon Sep 17 00:00:00 2001 From: Boris Maslakov Date: Sat, 2 Sep 2017 21:10:52 +0300 Subject: [PATCH 1/3] implement Maybe.switchIfEmpty(Single) --- src/main/java/io/reactivex/Maybe.java | 27 +++- ...ty.java => MaybeSwitchIfEmptyToMaybe.java} | 4 +- .../maybe/MaybeSwitchIfEmptyToSingle.java | 120 ++++++++++++++++++ ...ava => MaybeSwitchIfEmptyToMaybeTest.java} | 12 +- .../maybe/MaybeSwitchIfEmptyToSingleTest.java | 118 +++++++++++++++++ 5 files changed, 266 insertions(+), 15 deletions(-) rename src/main/java/io/reactivex/internal/operators/maybe/{MaybeSwitchIfEmpty.java => MaybeSwitchIfEmptyToMaybe.java} (95%) create mode 100644 src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingle.java rename src/test/java/io/reactivex/internal/operators/maybe/{MaybeSwitchIfEmptyTest.java => MaybeSwitchIfEmptyToMaybeTest.java} (91%) create mode 100644 src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingleTest.java diff --git a/src/main/java/io/reactivex/Maybe.java b/src/main/java/io/reactivex/Maybe.java index 9e468e9d6d..a6c737f525 100644 --- a/src/main/java/io/reactivex/Maybe.java +++ b/src/main/java/io/reactivex/Maybe.java @@ -2213,7 +2213,7 @@ public final Single count() { @SchedulerSupport(SchedulerSupport.NONE) public final Maybe defaultIfEmpty(T defaultItem) { ObjectHelper.requireNonNull(defaultItem, "item is null"); - return switchIfEmpty(just(defaultItem)); + return switchIfEmpty(Single.just(defaultItem)); } @@ -3817,7 +3817,30 @@ public final > E subscribeWith(E observer) { @SchedulerSupport(SchedulerSupport.NONE) public final Maybe switchIfEmpty(MaybeSource other) { ObjectHelper.requireNonNull(other, "other is null"); - return RxJavaPlugins.onAssembly(new MaybeSwitchIfEmpty(this, other)); + return RxJavaPlugins.onAssembly(new MaybeSwitchIfEmptyToMaybe(this, other)); + } + + /** + * Returns a Maybe that emits the items emitted by the source Maybe or the item of an alternate + * SingleSource if the current Maybe is empty. + *

+ * + *

+ *

+ *
Scheduler:
+ *
{@code switchIfEmpty} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param other + * the alternate SingleSource to subscribe to if the main does not emit any items + * @return a Maybe that emits the items emitted by the source Maybe or the item of an + * alternate SingleSource if the source Maybe is empty. + */ + @CheckReturnValue + @SchedulerSupport(SchedulerSupport.NONE) + public final Maybe switchIfEmpty(SingleSource other) { + ObjectHelper.requireNonNull(other, "other is null"); + return RxJavaPlugins.onAssembly(new MaybeSwitchIfEmptyToSingle(this, other)); } /** diff --git a/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmpty.java b/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybe.java similarity index 95% rename from src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmpty.java rename to src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybe.java index 396714eb7b..fd2d5c6156 100644 --- a/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmpty.java +++ b/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybe.java @@ -24,11 +24,11 @@ * * @param the value type */ -public final class MaybeSwitchIfEmpty extends AbstractMaybeWithUpstream { +public final class MaybeSwitchIfEmptyToMaybe extends AbstractMaybeWithUpstream { final MaybeSource other; - public MaybeSwitchIfEmpty(MaybeSource source, MaybeSource other) { + public MaybeSwitchIfEmptyToMaybe(MaybeSource source, MaybeSource other) { super(source); this.other = other; } diff --git a/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingle.java b/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingle.java new file mode 100644 index 0000000000..dd4caa22d1 --- /dev/null +++ b/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingle.java @@ -0,0 +1,120 @@ +/** + * 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.internal.operators.maybe; + +import io.reactivex.MaybeObserver; +import io.reactivex.MaybeSource; +import io.reactivex.SingleObserver; +import io.reactivex.SingleSource; +import io.reactivex.disposables.Disposable; +import io.reactivex.internal.disposables.DisposableHelper; + +import java.util.concurrent.atomic.AtomicReference; + +/** + * Subscribes to the other source if the main source is empty. + * + * @param the value type + */ +public final class MaybeSwitchIfEmptyToSingle extends AbstractMaybeWithUpstream { + + final SingleSource other; + + public MaybeSwitchIfEmptyToSingle(MaybeSource source, SingleSource other) { + super(source); + this.other = other; + } + + @Override + protected void subscribeActual(MaybeObserver observer) { + source.subscribe(new SwitchIfEmptyMaybeObserver(observer, other)); + } + + static final class SwitchIfEmptyMaybeObserver + extends AtomicReference + implements MaybeObserver, Disposable { + + private static final long serialVersionUID = 4603919676453758899L; + + final MaybeObserver actual; + + final SingleSource other; + + SwitchIfEmptyMaybeObserver(MaybeObserver actual, SingleSource other) { + this.actual = actual; + this.other = other; + } + + @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)) { + actual.onSubscribe(this); + } + } + + @Override + public void onSuccess(T value) { + actual.onSuccess(value); + } + + @Override + public void onError(Throwable e) { + actual.onError(e); + } + + @Override + public void onComplete() { + Disposable d = get(); + if (d != DisposableHelper.DISPOSED) { + if (compareAndSet(d, null)) { + other.subscribe(new OtherSingleObserver(actual, this)); + } + } + } + + static final class OtherSingleObserver implements SingleObserver { + + final MaybeObserver actual; + + final AtomicReference parent; + OtherSingleObserver(MaybeObserver actual, AtomicReference parent) { + this.actual = actual; + this.parent = parent; + } + @Override + public void onSubscribe(Disposable d) { + DisposableHelper.setOnce(parent, d); + } + @Override + public void onSuccess(T value) { + actual.onSuccess(value); + } + @Override + public void onError(Throwable e) { + actual.onError(e); + } + } + + } +} diff --git a/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyTest.java b/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybeTest.java similarity index 91% rename from src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyTest.java rename to src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybeTest.java index 91ebad9948..6cb27b733b 100644 --- a/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyTest.java +++ b/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybeTest.java @@ -24,7 +24,7 @@ import io.reactivex.processors.PublishProcessor; import io.reactivex.schedulers.Schedulers; -public class MaybeSwitchIfEmptyTest { +public class MaybeSwitchIfEmptyToMaybeTest { @Test public void nonEmpty() { @@ -36,16 +36,6 @@ public void empty() { Maybe.empty().switchIfEmpty(Maybe.just(2)).test().assertResult(2); } - @Test - public void defaultIfEmptyNonEmpty() { - Maybe.just(1).defaultIfEmpty(2).test().assertResult(1); - } - - @Test - public void defaultIfEmptyEmpty() { - Maybe.empty().defaultIfEmpty(2).test().assertResult(2); - } - @Test public void error() { Maybe.error(new TestException()).switchIfEmpty(Maybe.just(2)) diff --git a/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingleTest.java b/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingleTest.java new file mode 100644 index 0000000000..c27743f543 --- /dev/null +++ b/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingleTest.java @@ -0,0 +1,118 @@ +/** + * 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.internal.operators.maybe; + +import io.reactivex.Maybe; +import io.reactivex.Single; +import io.reactivex.TestHelper; +import io.reactivex.exceptions.TestException; +import io.reactivex.functions.Function; +import io.reactivex.observers.TestObserver; +import io.reactivex.processors.PublishProcessor; +import io.reactivex.schedulers.Schedulers; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class MaybeSwitchIfEmptyToSingleTest { + + @Test + public void nonEmpty() { + Maybe.just(1).switchIfEmpty(Single.just(2)).test().assertResult(1); + } + + @Test + public void empty() { + Maybe.empty().switchIfEmpty(Single.just(2)).test().assertResult(2); + } + + @Test + public void defaultIfEmptyNonEmpty() { + Maybe.just(1).defaultIfEmpty(2).test().assertResult(1); + } + + @Test + public void defaultIfEmptyEmpty() { + Maybe.empty().defaultIfEmpty(2).test().assertResult(2); + } + + @Test + public void error() { + Maybe.error(new TestException()).switchIfEmpty(Single.just(2)) + .test().assertFailure(TestException.class); + } + + @Test + public void errorOther() { + Maybe.empty().switchIfEmpty(Single.error(new TestException())) + .test().assertFailure(TestException.class); + } + + @Test + public void dispose() { + PublishProcessor pp = PublishProcessor.create(); + + TestObserver ts = pp.singleElement().switchIfEmpty(Single.just(2)).test(); + + assertTrue(pp.hasSubscribers()); + + ts.cancel(); + + assertFalse(pp.hasSubscribers()); + } + + + @Test + public void isDisposed() { + PublishProcessor pp = PublishProcessor.create(); + + TestHelper.checkDisposed(pp.singleElement().switchIfEmpty(Single.just(2))); + } + + @Test + public void doubleOnSubscribe() { + TestHelper.checkDoubleOnSubscribeMaybe(new Function, Maybe>() { + @Override + public Maybe apply(Maybe f) throws Exception { + return f.switchIfEmpty(Single.just(2)); + } + }); + } + + @Test + public void emptyCancelRace() { + for (int i = 0; i < 500; i++) { + final PublishProcessor pp = PublishProcessor.create(); + + final TestObserver ts = pp.singleElement().switchIfEmpty(Single.just(2)).test(); + + Runnable r1 = new Runnable() { + @Override + public void run() { + pp.onComplete(); + } + }; + + Runnable r2 = new Runnable() { + @Override + public void run() { + ts.cancel(); + } + }; + + TestHelper.race(r1, r2, Schedulers.single()); + } + } +} From 31d2d816bea885ac3ef8746dfa9e0c58a6afed9c Mon Sep 17 00:00:00 2001 From: Boris Maslakov Date: Sat, 2 Sep 2017 22:34:00 +0300 Subject: [PATCH 2/3] switchIfEmpty(Single) returns single; remove all changes unrelated to the PR --- src/main/java/io/reactivex/Maybe.java | 12 ++++---- ...tyToMaybe.java => MaybeSwitchIfEmpty.java} | 4 +-- ...gle.java => MaybeSwitchIfEmptySingle.java} | 30 +++++++++++-------- ...java => MaybeSwitchIfEmptySingleTest.java} | 16 ++-------- ...eTest.java => MaybeSwitchIfEmptyTest.java} | 12 +++++++- 5 files changed, 39 insertions(+), 35 deletions(-) rename src/main/java/io/reactivex/internal/operators/maybe/{MaybeSwitchIfEmptyToMaybe.java => MaybeSwitchIfEmpty.java} (95%) rename src/main/java/io/reactivex/internal/operators/maybe/{MaybeSwitchIfEmptyToSingle.java => MaybeSwitchIfEmptySingle.java} (78%) rename src/test/java/io/reactivex/internal/operators/maybe/{MaybeSwitchIfEmptyToSingleTest.java => MaybeSwitchIfEmptySingleTest.java} (86%) rename src/test/java/io/reactivex/internal/operators/maybe/{MaybeSwitchIfEmptyToMaybeTest.java => MaybeSwitchIfEmptyTest.java} (91%) diff --git a/src/main/java/io/reactivex/Maybe.java b/src/main/java/io/reactivex/Maybe.java index a6c737f525..c6e98ea516 100644 --- a/src/main/java/io/reactivex/Maybe.java +++ b/src/main/java/io/reactivex/Maybe.java @@ -2213,7 +2213,7 @@ public final Single count() { @SchedulerSupport(SchedulerSupport.NONE) public final Maybe defaultIfEmpty(T defaultItem) { ObjectHelper.requireNonNull(defaultItem, "item is null"); - return switchIfEmpty(Single.just(defaultItem)); + return switchIfEmpty(just(defaultItem)); } @@ -3817,11 +3817,11 @@ public final > E subscribeWith(E observer) { @SchedulerSupport(SchedulerSupport.NONE) public final Maybe switchIfEmpty(MaybeSource other) { ObjectHelper.requireNonNull(other, "other is null"); - return RxJavaPlugins.onAssembly(new MaybeSwitchIfEmptyToMaybe(this, other)); + return RxJavaPlugins.onAssembly(new MaybeSwitchIfEmpty(this, other)); } /** - * Returns a Maybe that emits the items emitted by the source Maybe or the item of an alternate + * Returns a Single that emits the items emitted by the source Maybe or the item of an alternate * SingleSource if the current Maybe is empty. *

* @@ -3833,14 +3833,14 @@ public final Maybe switchIfEmpty(MaybeSource other) { * * @param other * the alternate SingleSource to subscribe to if the main does not emit any items - * @return a Maybe that emits the items emitted by the source Maybe or the item of an + * @return a Single that emits the items emitted by the source Maybe or the item of an * alternate SingleSource if the source Maybe is empty. */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) - public final Maybe switchIfEmpty(SingleSource other) { + public final Single switchIfEmpty(SingleSource other) { ObjectHelper.requireNonNull(other, "other is null"); - return RxJavaPlugins.onAssembly(new MaybeSwitchIfEmptyToSingle(this, other)); + return RxJavaPlugins.onAssembly(new MaybeSwitchIfEmptySingle(this, other)); } /** diff --git a/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybe.java b/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmpty.java similarity index 95% rename from src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybe.java rename to src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmpty.java index fd2d5c6156..396714eb7b 100644 --- a/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybe.java +++ b/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmpty.java @@ -24,11 +24,11 @@ * * @param the value type */ -public final class MaybeSwitchIfEmptyToMaybe extends AbstractMaybeWithUpstream { +public final class MaybeSwitchIfEmpty extends AbstractMaybeWithUpstream { final MaybeSource other; - public MaybeSwitchIfEmptyToMaybe(MaybeSource source, MaybeSource other) { + public MaybeSwitchIfEmpty(MaybeSource source, MaybeSource other) { super(source); this.other = other; } diff --git a/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingle.java b/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptySingle.java similarity index 78% rename from src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingle.java rename to src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptySingle.java index dd4caa22d1..89615edd03 100644 --- a/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingle.java +++ b/src/main/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptySingle.java @@ -13,12 +13,10 @@ package io.reactivex.internal.operators.maybe; -import io.reactivex.MaybeObserver; -import io.reactivex.MaybeSource; -import io.reactivex.SingleObserver; -import io.reactivex.SingleSource; +import io.reactivex.*; import io.reactivex.disposables.Disposable; import io.reactivex.internal.disposables.DisposableHelper; +import io.reactivex.internal.fuseable.HasUpstreamMaybeSource; import java.util.concurrent.atomic.AtomicReference; @@ -27,17 +25,23 @@ * * @param the value type */ -public final class MaybeSwitchIfEmptyToSingle extends AbstractMaybeWithUpstream { +public final class MaybeSwitchIfEmptySingle extends Single implements HasUpstreamMaybeSource { + final MaybeSource source; final SingleSource other; - public MaybeSwitchIfEmptyToSingle(MaybeSource source, SingleSource other) { - super(source); + public MaybeSwitchIfEmptySingle(MaybeSource source, SingleSource other) { + this.source = source; this.other = other; } @Override - protected void subscribeActual(MaybeObserver observer) { + public MaybeSource source() { + return source; + } + + @Override + protected void subscribeActual(SingleObserver observer) { source.subscribe(new SwitchIfEmptyMaybeObserver(observer, other)); } @@ -47,11 +51,11 @@ static final class SwitchIfEmptyMaybeObserver private static final long serialVersionUID = 4603919676453758899L; - final MaybeObserver actual; + final SingleObserver actual; final SingleSource other; - SwitchIfEmptyMaybeObserver(MaybeObserver actual, SingleSource other) { + SwitchIfEmptyMaybeObserver(SingleObserver actual, SingleSource other) { this.actual = actual; this.other = other; } @@ -95,10 +99,10 @@ public void onComplete() { static final class OtherSingleObserver implements SingleObserver { - final MaybeObserver actual; + final SingleObserver actual; final AtomicReference parent; - OtherSingleObserver(MaybeObserver actual, AtomicReference parent) { + OtherSingleObserver(SingleObserver actual, AtomicReference parent) { this.actual = actual; this.parent = parent; } @@ -117,4 +121,4 @@ public void onError(Throwable e) { } } -} +} \ No newline at end of file diff --git a/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingleTest.java b/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptySingleTest.java similarity index 86% rename from src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingleTest.java rename to src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptySingleTest.java index c27743f543..d21eccb211 100644 --- a/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToSingleTest.java +++ b/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptySingleTest.java @@ -26,7 +26,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class MaybeSwitchIfEmptyToSingleTest { +public class MaybeSwitchIfEmptySingleTest { @Test public void nonEmpty() { @@ -38,16 +38,6 @@ public void empty() { Maybe.empty().switchIfEmpty(Single.just(2)).test().assertResult(2); } - @Test - public void defaultIfEmptyNonEmpty() { - Maybe.just(1).defaultIfEmpty(2).test().assertResult(1); - } - - @Test - public void defaultIfEmptyEmpty() { - Maybe.empty().defaultIfEmpty(2).test().assertResult(2); - } - @Test public void error() { Maybe.error(new TestException()).switchIfEmpty(Single.just(2)) @@ -83,9 +73,9 @@ public void isDisposed() { @Test public void doubleOnSubscribe() { - TestHelper.checkDoubleOnSubscribeMaybe(new Function, Maybe>() { + TestHelper.checkDoubleOnSubscribeMaybeToSingle(new Function, Single>() { @Override - public Maybe apply(Maybe f) throws Exception { + public Single apply(Maybe f) throws Exception { return f.switchIfEmpty(Single.just(2)); } }); diff --git a/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybeTest.java b/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyTest.java similarity index 91% rename from src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybeTest.java rename to src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyTest.java index 6cb27b733b..91ebad9948 100644 --- a/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyToMaybeTest.java +++ b/src/test/java/io/reactivex/internal/operators/maybe/MaybeSwitchIfEmptyTest.java @@ -24,7 +24,7 @@ import io.reactivex.processors.PublishProcessor; import io.reactivex.schedulers.Schedulers; -public class MaybeSwitchIfEmptyToMaybeTest { +public class MaybeSwitchIfEmptyTest { @Test public void nonEmpty() { @@ -36,6 +36,16 @@ public void empty() { Maybe.empty().switchIfEmpty(Maybe.just(2)).test().assertResult(2); } + @Test + public void defaultIfEmptyNonEmpty() { + Maybe.just(1).defaultIfEmpty(2).test().assertResult(1); + } + + @Test + public void defaultIfEmptyEmpty() { + Maybe.empty().defaultIfEmpty(2).test().assertResult(2); + } + @Test public void error() { Maybe.error(new TestException()).switchIfEmpty(Maybe.just(2)) From 4dadbb9bc017f6aa7236f3a03ba04c56eed8ed65 Mon Sep 17 00:00:00 2001 From: Boris Maslakov Date: Sat, 2 Sep 2017 22:36:19 +0300 Subject: [PATCH 3/3] add 'experimental' annotation --- src/main/java/io/reactivex/Maybe.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/io/reactivex/Maybe.java b/src/main/java/io/reactivex/Maybe.java index c6e98ea516..daff77cff4 100644 --- a/src/main/java/io/reactivex/Maybe.java +++ b/src/main/java/io/reactivex/Maybe.java @@ -3835,7 +3835,9 @@ public final Maybe switchIfEmpty(MaybeSource other) { * the alternate SingleSource to subscribe to if the main does not emit any items * @return a Single that emits the items emitted by the source Maybe or the item of an * alternate SingleSource if the source Maybe is empty. + * @since 2.1.4 - experimental */ + @Experimental @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) public final Single switchIfEmpty(SingleSource other) {