Skip to content

Commit 57bd1a9

Browse files
authored
3.x: Add concatMapX operators (aliases) (#6879)
1 parent 4257ef5 commit 57bd1a9

10 files changed

+1063
-241
lines changed

docs/Operator-Matrix.md

+224-234
Large diffs are not rendered by default.

src/main/java/io/reactivex/rxjava3/core/Maybe.java

+63-7
Original file line numberDiff line numberDiff line change
@@ -2828,12 +2828,13 @@ public final <R> Maybe<R> compose(@NonNull MaybeTransformer<? super T, ? extends
28282828
* Returns a {@code Maybe} that is based on applying a specified function to the item emitted by the current {@code Maybe},
28292829
* where that function returns a {@link MaybeSource}.
28302830
* <p>
2831-
* <img width="640" height="356" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.flatMap.png" alt="">
2831+
* <img width="640" height="216" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.concatMap.png" alt="">
2832+
* <p>
2833+
* Note that flatMap and concatMap for {@code Maybe} is the same operation.
28322834
* <dl>
28332835
* <dt><b>Scheduler:</b></dt>
28342836
* <dd>{@code concatMap} does not operate by default on a particular {@link Scheduler}.</dd>
28352837
* </dl>
2836-
* <p>Note that flatMap and concatMap for {@code Maybe} is the same operation.
28372838
* @param <R> the result value type
28382839
* @param mapper
28392840
* a function that, when applied to the item emitted by the current {@code Maybe}, returns a {@code MaybeSource}
@@ -2845,8 +2846,63 @@ public final <R> Maybe<R> compose(@NonNull MaybeTransformer<? super T, ? extends
28452846
@NonNull
28462847
@SchedulerSupport(SchedulerSupport.NONE)
28472848
public final <R> Maybe<R> concatMap(@NonNull Function<? super T, ? extends MaybeSource<? extends R>> mapper) {
2848-
Objects.requireNonNull(mapper, "mapper is null");
2849-
return RxJavaPlugins.onAssembly(new MaybeFlatten<>(this, mapper));
2849+
return flatMap(mapper);
2850+
}
2851+
2852+
/**
2853+
* Returns a {@link Completable} that completes based on applying a specified function to the item emitted by the
2854+
* current {@code Maybe}, where that function returns a {@code Completable}.
2855+
* <p>
2856+
* <img width="640" height="304" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.concatMapCompletable.png" alt="">
2857+
* <p>
2858+
* This operator is an alias for {@link #flatMapCompletable(Function)}.
2859+
* <dl>
2860+
* <dt><b>Scheduler:</b></dt>
2861+
* <dd>{@code concatMapCompletable} does not operate by default on a particular {@link Scheduler}.</dd>
2862+
* </dl>
2863+
*
2864+
* @param mapper
2865+
* a function that, when applied to the item emitted by the current {@code Maybe}, returns a
2866+
* {@code Completable}
2867+
* @return the new {@code Completable} instance
2868+
* @throws NullPointerException if {@code mapper} is {@code null}
2869+
* @see <a href="http://reactivex.io/documentation/operators/flatmap.html">ReactiveX operators documentation: FlatMap</a>
2870+
* @since 3.0.0
2871+
*/
2872+
@CheckReturnValue
2873+
@NonNull
2874+
@SchedulerSupport(SchedulerSupport.NONE)
2875+
public final Completable concatMapCompletable(@NonNull Function<? super T, ? extends CompletableSource> mapper) {
2876+
return flatMapCompletable(mapper);
2877+
}
2878+
2879+
/**
2880+
* Returns a {@code Maybe} based on applying a specified function to the item emitted by the
2881+
* current {@code Maybe}, where that function returns a {@link Single}.
2882+
* When this {@code Maybe} just completes the resulting {@code Maybe} completes as well.
2883+
* <p>
2884+
* <img width="640" height="315" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.concatMapSingle.png" alt="">
2885+
* <p>
2886+
* This operator is an alias for {@link #flatMapSingleElement(Function)}.
2887+
* <dl>
2888+
* <dt><b>Scheduler:</b></dt>
2889+
* <dd>{@code concatMapSingle} does not operate by default on a particular {@link Scheduler}.</dd>
2890+
* </dl>
2891+
*
2892+
* @param <R> the result value type
2893+
* @param mapper
2894+
* a function that, when applied to the item emitted by the current {@code Maybe}, returns a
2895+
* {@code Single}
2896+
* @return the new {@code Maybe} instance
2897+
* @throws NullPointerException if {@code mapper} is {@code null}
2898+
* @see <a href="http://reactivex.io/documentation/operators/flatmap.html">ReactiveX operators documentation: FlatMap</a>
2899+
* @since 3.0.0
2900+
*/
2901+
@CheckReturnValue
2902+
@NonNull
2903+
@SchedulerSupport(SchedulerSupport.NONE)
2904+
public final <R> Maybe<R> concatMapSingle(@NonNull Function<? super T, ? extends SingleSource<? extends R>> mapper) {
2905+
return flatMapSingleElement(mapper);
28502906
}
28512907

28522908
/**
@@ -3732,7 +3788,7 @@ public final <R> Flowable<R> flatMapPublisher(@NonNull Function<? super T, ? ext
37323788
* current {@code Maybe}, where that function returns a {@code Single}.
37333789
* When this {@code Maybe} completes a {@link NoSuchElementException} will be thrown.
37343790
* <p>
3735-
* <img width="640" height="356" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.flatMapSingle.png" alt="">
3791+
* <img width="640" height="346" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.flatMapSingle3.png" alt="">
37363792
* <dl>
37373793
* <dt><b>Scheduler:</b></dt>
37383794
* <dd>{@code flatMapSingle} does not operate by default on a particular {@link Scheduler}.</dd>
@@ -3759,7 +3815,7 @@ public final <R> Single<R> flatMapSingle(@NonNull Function<? super T, ? extends
37593815
* current {@code Maybe}, where that function returns a {@link Single}.
37603816
* When this {@code Maybe} just completes the resulting {@code Maybe} completes as well.
37613817
* <p>
3762-
* <img width="640" height="356" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.flatMapSingle.png" alt="">
3818+
* <img width="640" height="315" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.flatMapSingle.png" alt="">
37633819
* <dl>
37643820
* <dt><b>Scheduler:</b></dt>
37653821
* <dd>{@code flatMapSingleElement} does not operate by default on a particular {@link Scheduler}.</dd>
@@ -3787,7 +3843,7 @@ public final <R> Maybe<R> flatMapSingleElement(@NonNull Function<? super T, ? ex
37873843
* Returns a {@link Completable} that completes based on applying a specified function to the item emitted by the
37883844
* current {@code Maybe}, where that function returns a {@code Completable}.
37893845
* <p>
3790-
* <img width="640" height="267" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.flatMapCompletable.png" alt="">
3846+
* <img width="640" height="303" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.flatMapCompletable3.png" alt="">
37913847
* <dl>
37923848
* <dt><b>Scheduler:</b></dt>
37933849
* <dd>{@code flatMapCompletable} does not operate by default on a particular {@link Scheduler}.</dd>

src/main/java/io/reactivex/rxjava3/core/Single.java

+80
Original file line numberDiff line numberDiff line change
@@ -2278,6 +2278,86 @@ public final <U> Single<U> cast(@NonNull Class<? extends U> clazz) {
22782278
return map(Functions.castFunction(clazz));
22792279
}
22802280

2281+
/**
2282+
* Returns a {@code Single} that is based on applying a specified function to the item emitted by the current {@code Single},
2283+
* where that function returns a {@link SingleSource}.
2284+
* <p>
2285+
* <img width="640" height="313" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Single.concatMap.png" alt="">
2286+
* <p>
2287+
* The operator is an alias for {@link #flatMap(Function)}
2288+
* <dl>
2289+
* <dt><b>Scheduler:</b></dt>
2290+
* <dd>{@code concatMap} does not operate by default on a particular {@link Scheduler}.</dd>
2291+
* </dl>
2292+
*
2293+
* @param <R> the result value type
2294+
* @param mapper
2295+
* a function that, when applied to the item emitted by the current {@code Single}, returns a {@code SingleSource}
2296+
* @return the new {@code Single} returned from {@code mapper} when applied to the item emitted by the current {@code Single}
2297+
* @throws NullPointerException if {@code mapper} is {@code null}
2298+
* @see <a href="http://reactivex.io/documentation/operators/flatmap.html">ReactiveX operators documentation: FlatMap</a>
2299+
*/
2300+
@CheckReturnValue
2301+
@NonNull
2302+
@SchedulerSupport(SchedulerSupport.NONE)
2303+
public final <R> Single<R> concatMap(@NonNull Function<? super T, ? extends SingleSource<? extends R>> mapper) {
2304+
Objects.requireNonNull(mapper, "mapper is null");
2305+
return RxJavaPlugins.onAssembly(new SingleFlatMap<>(this, mapper));
2306+
}
2307+
2308+
/**
2309+
* Returns a {@link Completable} that completes based on applying a specified function to the item emitted by the
2310+
* current {@code Single}, where that function returns a {@link CompletableSource}.
2311+
* <p>
2312+
* <img width="640" height="298" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Single.concatMapCompletable.png" alt="">
2313+
* <p>
2314+
* The operator is an alias for {@link #flatMapCompletable(Function)}.
2315+
* <dl>
2316+
* <dt><b>Scheduler:</b></dt>
2317+
* <dd>{@code concatMapCompletable} does not operate by default on a particular {@link Scheduler}.</dd>
2318+
* </dl>
2319+
*
2320+
* @param mapper
2321+
* a function that, when applied to the item emitted by the current {@code Single}, returns a
2322+
* {@code CompletableSource}
2323+
* @return the new {@code Completable} instance
2324+
* @throws NullPointerException if {@code mapper} is {@code null}
2325+
* @see <a href="http://reactivex.io/documentation/operators/flatmap.html">ReactiveX operators documentation: FlatMap</a>
2326+
* @since 3.0.0
2327+
*/
2328+
@CheckReturnValue
2329+
@NonNull
2330+
@SchedulerSupport(SchedulerSupport.NONE)
2331+
public final Completable concatMapCompletable(@NonNull Function<? super T, ? extends CompletableSource> mapper) {
2332+
return flatMapCompletable(mapper);
2333+
}
2334+
2335+
/**
2336+
* Returns a {@link Maybe} that is based on applying a specified function to the item emitted by the current {@code Single},
2337+
* where that function returns a {@link MaybeSource}.
2338+
* <p>
2339+
* <img width="640" height="254" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Single.concatMapMaybe.png" alt="">
2340+
* <p>
2341+
* The operator is an alias for {@link #flatMapMaybe(Function)}.
2342+
* <dl>
2343+
* <dt><b>Scheduler:</b></dt>
2344+
* <dd>{@code concatMapMaybe} does not operate by default on a particular {@link Scheduler}.</dd>
2345+
* </dl>
2346+
*
2347+
* @param <R> the result value type
2348+
* @param mapper
2349+
* a function that, when applied to the item emitted by the current {@code Single}, returns a {@code MaybeSource}
2350+
* @return the new {@code Maybe} returned from {@code mapper} when applied to the item emitted by the current {@code Single}
2351+
* @throws NullPointerException if {@code mapper} is {@code null}
2352+
* @see <a href="http://reactivex.io/documentation/operators/flatmap.html">ReactiveX operators documentation: FlatMap</a>
2353+
*/
2354+
@CheckReturnValue
2355+
@NonNull
2356+
@SchedulerSupport(SchedulerSupport.NONE)
2357+
public final <R> Maybe<R> concatMapMaybe(@NonNull Function<? super T, ? extends MaybeSource<? extends R>> mapper) {
2358+
return flatMapMaybe(mapper);
2359+
}
2360+
22812361
/**
22822362
* Returns a {@link Flowable} that emits the item emitted by the current {@code Single}, then the item emitted by the
22832363
* specified {@link SingleSource}.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Copyright (c) 2016-present, RxJava Contributors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
5+
* compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is
10+
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
11+
* the License for the specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package io.reactivex.rxjava3.internal.operators.maybe;
15+
16+
import org.junit.Test;
17+
18+
import io.reactivex.rxjava3.core.*;
19+
import io.reactivex.rxjava3.exceptions.TestException;
20+
import io.reactivex.rxjava3.functions.Function;
21+
import io.reactivex.rxjava3.testsupport.TestHelper;
22+
23+
public class MaybeConcatMapCompletableTest extends RxJavaTest {
24+
25+
@Test
26+
public void dispose() {
27+
TestHelper.checkDisposed(Maybe.just(1).concatMapCompletable(new Function<Integer, Completable>() {
28+
@Override
29+
public Completable apply(Integer v) throws Exception {
30+
return Completable.complete();
31+
}
32+
}));
33+
}
34+
35+
@Test
36+
public void mapperThrows() {
37+
Maybe.just(1)
38+
.concatMapCompletable(new Function<Integer, Completable>() {
39+
@Override
40+
public Completable apply(Integer v) throws Exception {
41+
throw new TestException();
42+
}
43+
})
44+
.test()
45+
.assertFailure(TestException.class);
46+
}
47+
48+
@Test
49+
public void mapperReturnsNull() {
50+
Maybe.just(1)
51+
.concatMapCompletable(new Function<Integer, Completable>() {
52+
@Override
53+
public Completable apply(Integer v) throws Exception {
54+
return null;
55+
}
56+
})
57+
.test()
58+
.assertFailure(NullPointerException.class);
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/**
2+
* Copyright (c) 2016-present, RxJava Contributors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
5+
* compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is
10+
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
11+
* the License for the specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package io.reactivex.rxjava3.internal.operators.maybe;
15+
16+
import org.junit.Test;
17+
18+
import io.reactivex.rxjava3.core.*;
19+
import io.reactivex.rxjava3.exceptions.TestException;
20+
import io.reactivex.rxjava3.functions.Function;
21+
import io.reactivex.rxjava3.testsupport.TestHelper;
22+
23+
public class MaybeConcatMapSingleTest extends RxJavaTest {
24+
@Test
25+
public void flatMapSingleElementValue() {
26+
Maybe.just(1).concatMapSingle(new Function<Integer, SingleSource<Integer>>() {
27+
@Override public SingleSource<Integer> apply(final Integer integer) throws Exception {
28+
if (integer == 1) {
29+
return Single.just(2);
30+
}
31+
32+
return Single.just(1);
33+
}
34+
})
35+
.test()
36+
.assertResult(2);
37+
}
38+
39+
@Test
40+
public void flatMapSingleElementValueDifferentType() {
41+
Maybe.just(1).concatMapSingle(new Function<Integer, SingleSource<String>>() {
42+
@Override public SingleSource<String> apply(final Integer integer) throws Exception {
43+
if (integer == 1) {
44+
return Single.just("2");
45+
}
46+
47+
return Single.just("1");
48+
}
49+
})
50+
.test()
51+
.assertResult("2");
52+
}
53+
54+
@Test
55+
public void flatMapSingleElementValueNull() {
56+
Maybe.just(1).concatMapSingle(new Function<Integer, SingleSource<Integer>>() {
57+
@Override public SingleSource<Integer> apply(final Integer integer) throws Exception {
58+
return null;
59+
}
60+
})
61+
.to(TestHelper.<Integer>testConsumer())
62+
.assertNoValues()
63+
.assertError(NullPointerException.class)
64+
.assertErrorMessage("The mapper returned a null SingleSource");
65+
}
66+
67+
@Test
68+
public void flatMapSingleElementValueErrorThrown() {
69+
Maybe.just(1).concatMapSingle(new Function<Integer, SingleSource<Integer>>() {
70+
@Override public SingleSource<Integer> apply(final Integer integer) throws Exception {
71+
throw new RuntimeException("something went terribly wrong!");
72+
}
73+
})
74+
.to(TestHelper.<Integer>testConsumer())
75+
.assertNoValues()
76+
.assertError(RuntimeException.class)
77+
.assertErrorMessage("something went terribly wrong!");
78+
}
79+
80+
@Test
81+
public void flatMapSingleElementError() {
82+
RuntimeException exception = new RuntimeException("test");
83+
84+
Maybe.error(exception).concatMapSingle(new Function<Object, SingleSource<Object>>() {
85+
@Override public SingleSource<Object> apply(final Object integer) throws Exception {
86+
return Single.just(new Object());
87+
}
88+
})
89+
.test()
90+
.assertError(exception);
91+
}
92+
93+
@Test
94+
public void flatMapSingleElementEmpty() {
95+
Maybe.<Integer>empty().concatMapSingle(new Function<Integer, SingleSource<Integer>>() {
96+
@Override public SingleSource<Integer> apply(final Integer integer) throws Exception {
97+
return Single.just(2);
98+
}
99+
})
100+
.test()
101+
.assertNoValues()
102+
.assertResult();
103+
}
104+
105+
@Test
106+
public void dispose() {
107+
TestHelper.checkDisposed(Maybe.just(1).concatMapSingle(new Function<Integer, SingleSource<Integer>>() {
108+
@Override
109+
public SingleSource<Integer> apply(final Integer integer) throws Exception {
110+
return Single.just(2);
111+
}
112+
}));
113+
}
114+
115+
@Test
116+
public void doubleOnSubscribe() {
117+
TestHelper.checkDoubleOnSubscribeMaybe(new Function<Maybe<Integer>, Maybe<Integer>>() {
118+
@Override
119+
public Maybe<Integer> apply(Maybe<Integer> m) throws Exception {
120+
return m.concatMapSingle(new Function<Integer, SingleSource<Integer>>() {
121+
@Override
122+
public SingleSource<Integer> apply(final Integer integer) throws Exception {
123+
return Single.just(2);
124+
}
125+
});
126+
}
127+
});
128+
}
129+
130+
@Test
131+
public void singleErrors() {
132+
Maybe.just(1)
133+
.concatMapSingle(new Function<Integer, SingleSource<Integer>>() {
134+
@Override
135+
public SingleSource<Integer> apply(final Integer integer) throws Exception {
136+
return Single.error(new TestException());
137+
}
138+
})
139+
.test()
140+
.assertFailure(TestException.class);
141+
}
142+
}

0 commit comments

Comments
 (0)