From 781191b7705b2e03fac51d0e2a0590d01fc631b1 Mon Sep 17 00:00:00 2001 From: Ben Christensen Date: Mon, 9 Sep 2013 15:51:07 -0700 Subject: [PATCH] Observable.concat: refactor varargs to overloads https://github.com/Netflix/RxJava/issues/359 Varargs cause compiler warnings As part of this I also changed this: ```java public static Observable concat(Observable> observables) ``` to ```java public static Observable concat(Observable> observables) ``` I documented the reasoning of this at https://github.com/Netflix/RxJava/issues/360#issuecomment-24121217 --- rxjava-core/src/main/java/rx/Observable.java | 226 +++++++++++++++++- .../java/rx/operators/OperationConcat.java | 2 +- rxjava-core/src/test/java/rx/ConcatTests.java | 57 +++++ .../src/test/java/rx/CovarianceTest.java | 81 ++++++- 4 files changed, 352 insertions(+), 14 deletions(-) create mode 100644 rxjava-core/src/test/java/rx/ConcatTests.java diff --git a/rxjava-core/src/main/java/rx/Observable.java b/rxjava-core/src/main/java/rx/Observable.java index c3e9379670..21d7ccb2a3 100644 --- a/rxjava-core/src/main/java/rx/Observable.java +++ b/rxjava-core/src/main/java/rx/Observable.java @@ -979,14 +979,232 @@ public static Observable merge(Observable... source) { *

* * - * @param source - * a series of Observables + * @param observables + * an Observable of Observables + * @return an Observable that emits items that are the result of combining the items emitted by + * the {@code source} Observables, one after the other + * @see MSDN: Observable.Concat Method + */ + public static Observable concat(Observable> observables) { + return create(OperationConcat.concat(observables)); + } + + /** + * Returns an Observable that emits the items emitted by two or more Observables, one after the + * other. + *

+ * + * + * @param t1 + * an Observable to be concatenated + * @param t2 + * an Observable to be concatenated + * an Observable to be concatenated + * @return an Observable that emits items that are the result of combining the items emitted by + * the {@code source} Observables, one after the other + * @see MSDN: Observable.Concat Method + */ + @SuppressWarnings("unchecked") + // suppress because the types are checked by the method signature before using a vararg + public static Observable concat(Observable t1, Observable t2) { + return create(OperationConcat.concat(t1, t2)); + } + + /** + * Returns an Observable that emits the items emitted by two or more Observables, one after the + * other. + *

+ * + * + * @param t1 + * an Observable to be concatenated + * @param t2 + * an Observable to be concatenated + * @param t3 + * an Observable to be concatenated + * an Observable to be concatenated + * @return an Observable that emits items that are the result of combining the items emitted by + * the {@code source} Observables, one after the other + * @see MSDN: Observable.Concat Method + */ + @SuppressWarnings("unchecked") + // suppress because the types are checked by the method signature before using a vararg + public static Observable concat(Observable t1, Observable t2, Observable t3) { + return create(OperationConcat.concat(t1, t2, t3)); + } + + /** + * Returns an Observable that emits the items emitted by two or more Observables, one after the + * other. + *

+ * + * + * @param t1 + * an Observable to be concatenated + * @param t2 + * an Observable to be concatenated + * @param t3 + * an Observable to be concatenated + * @param t4 + * an Observable to be concatenated + * @return an Observable that emits items that are the result of combining the items emitted by + * the {@code source} Observables, one after the other + * @see MSDN: Observable.Concat Method + */ + @SuppressWarnings("unchecked") + // suppress because the types are checked by the method signature before using a vararg + public static Observable concat(Observable t1, Observable t2, Observable t3, Observable t4) { + return create(OperationConcat.concat(t1, t2, t3, t4)); + } + + /** + * Returns an Observable that emits the items emitted by two or more Observables, one after the + * other. + *

+ * + * + * @param t1 + * an Observable to be concatenated + * @param t2 + * an Observable to be concatenated + * @param t3 + * an Observable to be concatenated + * @param t4 + * an Observable to be concatenated + * @param t5 + * an Observable to be concatenated + * @return an Observable that emits items that are the result of combining the items emitted by + * the {@code source} Observables, one after the other + * @see MSDN: Observable.Concat Method + */ + @SuppressWarnings("unchecked") + // suppress because the types are checked by the method signature before using a vararg + public static Observable concat(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5) { + return create(OperationConcat.concat(t1, t2, t3, t4, t5)); + } + + /** + * Returns an Observable that emits the items emitted by two or more Observables, one after the + * other. + *

+ * + * + * @param t1 + * an Observable to be concatenated + * @param t2 + * an Observable to be concatenated + * @param t3 + * an Observable to be concatenated + * @param t4 + * an Observable to be concatenated + * @param t5 + * an Observable to be concatenated + * @param t6 + * an Observable to be concatenated + * @return an Observable that emits items that are the result of combining the items emitted by + * the {@code source} Observables, one after the other + * @see MSDN: Observable.Concat Method + */ + @SuppressWarnings("unchecked") + // suppress because the types are checked by the method signature before using a vararg + public static Observable concat(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5, Observable t6) { + return create(OperationConcat.concat(t1, t2, t3, t4, t5, t6)); + } + + /** + * Returns an Observable that emits the items emitted by two or more Observables, one after the + * other. + *

+ * + * + * @param t1 + * an Observable to be concatenated + * @param t2 + * an Observable to be concatenated + * @param t3 + * an Observable to be concatenated + * @param t4 + * an Observable to be concatenated + * @param t5 + * an Observable to be concatenated + * @param t6 + * an Observable to be concatenated + * @param t7 + * an Observable to be concatenated * @return an Observable that emits items that are the result of combining the items emitted by * the {@code source} Observables, one after the other * @see MSDN: Observable.Concat Method */ - public static Observable concat(Observable... source) { - return create(OperationConcat.concat(source)); + @SuppressWarnings("unchecked") + // suppress because the types are checked by the method signature before using a vararg + public static Observable concat(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5, Observable t6, Observable t7) { + return create(OperationConcat.concat(t1, t2, t3, t4, t5, t6, t7)); + } + + /** + * Returns an Observable that emits the items emitted by two or more Observables, one after the + * other. + *

+ * + * + * @param t1 + * an Observable to be concatenated + * @param t2 + * an Observable to be concatenated + * @param t3 + * an Observable to be concatenated + * @param t4 + * an Observable to be concatenated + * @param t5 + * an Observable to be concatenated + * @param t6 + * an Observable to be concatenated + * @param t7 + * an Observable to be concatenated + * @param t8 + * an Observable to be concatenated + * @return an Observable that emits items that are the result of combining the items emitted by + * the {@code source} Observables, one after the other + * @see MSDN: Observable.Concat Method + */ + @SuppressWarnings("unchecked") + // suppress because the types are checked by the method signature before using a vararg + public static Observable concat(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5, Observable t6, Observable t7, Observable t8) { + return create(OperationConcat.concat(t1, t2, t3, t4, t5, t6, t7, t8)); + } + + /** + * Returns an Observable that emits the items emitted by two or more Observables, one after the + * other. + *

+ * + * + * @param t1 + * an Observable to be concatenated + * @param t2 + * an Observable to be concatenated + * @param t3 + * an Observable to be concatenated + * @param t4 + * an Observable to be concatenated + * @param t5 + * an Observable to be concatenated + * @param t6 + * an Observable to be concatenated + * @param t7 + * an Observable to be concatenated + * @param t8 + * an Observable to be concatenated + * @param t9 + * an Observable to be concatenated + * @return an Observable that emits items that are the result of combining the items emitted by + * the {@code source} Observables, one after the other + * @see MSDN: Observable.Concat Method + */ + @SuppressWarnings("unchecked") + // suppress because the types are checked by the method signature before using a vararg + public static Observable concat(Observable t1, Observable t2, Observable t3, Observable t4, Observable t5, Observable t6, Observable t7, Observable t8, Observable t9) { + return create(OperationConcat.concat(t1, t2, t3, t4, t5, t6, t7, t8, t9)); } /** diff --git a/rxjava-core/src/main/java/rx/operators/OperationConcat.java b/rxjava-core/src/main/java/rx/operators/OperationConcat.java index 3a2d480608..734751e9d0 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationConcat.java +++ b/rxjava-core/src/main/java/rx/operators/OperationConcat.java @@ -60,7 +60,7 @@ public static OnSubscribeFunc concat(final Observable... seq return concat(Observable.from(sequences)); } - public static OnSubscribeFunc concat(final List> sequences) { + public static OnSubscribeFunc concat(final Iterable> sequences) { return concat(Observable.from(sequences)); } diff --git a/rxjava-core/src/test/java/rx/ConcatTests.java b/rxjava-core/src/test/java/rx/ConcatTests.java new file mode 100644 index 0000000000..524b7fd73f --- /dev/null +++ b/rxjava-core/src/test/java/rx/ConcatTests.java @@ -0,0 +1,57 @@ +package rx; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + +public class ConcatTests { + + @Test + public void testConcatSimple() { + Observable o1 = Observable.from("one", "two"); + Observable o2 = Observable.from("three", "four"); + + List values = Observable.concat(o1, o2).toList().toBlockingObservable().single(); + + assertEquals("one", values.get(0)); + assertEquals("two", values.get(1)); + assertEquals("three", values.get(2)); + assertEquals("four", values.get(3)); + } + + @Test + public void testConcatWithObservableOfObservable() { + Observable o1 = Observable.from("one", "two"); + Observable o2 = Observable.from("three", "four"); + Observable o3 = Observable.from("five", "six"); + + Observable> os = Observable.from(o1, o2, o3); + + List values = Observable.concat(os).toList().toBlockingObservable().single(); + + assertEquals("one", values.get(0)); + assertEquals("two", values.get(1)); + assertEquals("three", values.get(2)); + assertEquals("four", values.get(3)); + } + + @Test + public void testConcatWithIterableOfObservable() { + Observable o1 = Observable.from("one", "two"); + Observable o2 = Observable.from("three", "four"); + Observable o3 = Observable.from("five", "six"); + + @SuppressWarnings("unchecked") + Iterable> is = Arrays.asList(o1, o2, o3); + + List values = Observable.concat(Observable.from(is)).toList().toBlockingObservable().single(); + + assertEquals("one", values.get(0)); + assertEquals("two", values.get(1)); + assertEquals("three", values.get(2)); + assertEquals("four", values.get(3)); + } +} diff --git a/rxjava-core/src/test/java/rx/CovarianceTest.java b/rxjava-core/src/test/java/rx/CovarianceTest.java index 2594f27677..5737cd767f 100644 --- a/rxjava-core/src/test/java/rx/CovarianceTest.java +++ b/rxjava-core/src/test/java/rx/CovarianceTest.java @@ -1,9 +1,14 @@ package rx; +import static org.junit.Assert.*; + import java.util.ArrayList; +import java.util.List; import org.junit.Test; +import rx.Observable.OnSubscribeFunc; +import rx.subscriptions.Subscriptions; import rx.util.functions.Action1; import rx.util.functions.Func2; @@ -19,11 +24,11 @@ public class CovarianceTest { */ @Test public void testCovarianceOfFrom() { - Observable.from(new HorrorMovie()); - Observable.from(new ArrayList()); + Observable. from(new HorrorMovie()); + Observable. from(new ArrayList()); // Observable.from(new Movie()); // may not compile } - + /** * This won't compile if super/extends isn't done correctly on generics */ @@ -31,9 +36,9 @@ public void testCovarianceOfFrom() { public void testCovarianceOfMerge() { Observable horrors = Observable.from(new HorrorMovie()); Observable> metaHorrors = Observable.just(horrors); - Observable.merge(metaHorrors); + Observable. merge(metaHorrors); } - + /** * This won't compile if super/extends isn't done correctly on generics */ @@ -47,7 +52,7 @@ public void testCovarianceOfZip() { Observable. zip(horrors, ratings, combine).toBlockingObservable().forEach(extendedAction); Observable. zip(horrors, ratings, combine).toBlockingObservable().forEach(action); Observable. zip(horrors, ratings, combine).toBlockingObservable().forEach(action); - + Observable. zip(horrors, ratings, combine); } @@ -64,10 +69,68 @@ public void testCovarianceOfCombineLatest() { Observable. combineLatest(horrors, ratings, combine).toBlockingObservable().forEach(extendedAction); Observable. combineLatest(horrors, ratings, combine).toBlockingObservable().forEach(action); Observable. combineLatest(horrors, ratings, combine).toBlockingObservable().forEach(action); - + Observable. combineLatest(horrors, ratings, combine); } + @Test + public void testConcatCovariance() { + Observable o1 = Observable. from(new HorrorMovie(), new Movie()); + Observable o2 = Observable.from(new Media(), new HorrorMovie()); + + Observable> os = Observable.from(o1, o2); + + List values = Observable.concat(os).toList().toBlockingObservable().single(); + } + + @Test + public void testConcatCovariance2() { + Observable o1 = Observable.from(new HorrorMovie(), new Movie(), new Media()); + Observable o2 = Observable.from(new Media(), new HorrorMovie()); + + Observable> os = Observable.from(o1, o2); + + List values = Observable.concat(os).toList().toBlockingObservable().single(); + } + + @Test + public void testConcatCovariance3() { + Observable o1 = Observable.from(new HorrorMovie(), new Movie()); + Observable o2 = Observable.from(new Media(), new HorrorMovie()); + + List values = Observable.concat(o1, o2).toList().toBlockingObservable().single(); + + assertTrue(values.get(0) instanceof HorrorMovie); + assertTrue(values.get(1) instanceof Movie); + assertTrue(values.get(2) instanceof Media); + assertTrue(values.get(3) instanceof HorrorMovie); + } + + @Test + public void testConcatCovariance4() { + + Observable o1 = Observable.create(new OnSubscribeFunc() { + + @Override + public Subscription onSubscribe(Observer o) { + o.onNext(new HorrorMovie()); + o.onNext(new Movie()); + // o.onNext(new Media()); // correctly doesn't compile + o.onCompleted(); + return Subscriptions.empty(); + } + }); + + Observable o2 = Observable.from(new Media(), new HorrorMovie()); + + List values = Observable.concat(o1, o2).toList().toBlockingObservable().single(); + + assertTrue(values.get(0) instanceof HorrorMovie); + assertTrue(values.get(1) instanceof Movie); + assertTrue(values.get(2) instanceof Media); + assertTrue(values.get(3) instanceof HorrorMovie); + } + Func2 combine = new Func2() { @Override public ExtendedResult call(Media m, Rating r) { @@ -81,14 +144,14 @@ public void call(Result t1) { System.out.println("Result: " + t1); } }; - + Action1 extendedAction = new Action1() { @Override public void call(ExtendedResult t1) { System.out.println("Result: " + t1); } }; - + static class Media { }