Suppose we have two observables Observable<Integer> o1
and Observable<Integer> o2
and each observable is producing strictly increasing sequence.
The task is to perform equivalent of full outer join on these two observables. For example join of
Observable.just(0, 2, 3, 6)
Observable.just(1, 2, 3, 4, 5, 6)
should produce
[ [0, _], [_, 1], [2, 2], [3, 3], [_, 4], [_, 5], [6, 6] ]
The join should be efficient and work well on very large or infinite streams.
The solution is easy in pull scenario. Is there an idiomatic rx way to achieve this?
There is no single operator for this but it is possible to compose the behavior from standard and extension operators:
static abstract class Pair implements Comparable<Pair> {
int value;
@Override
public int compareTo(Pair o) {
return Integer.compare(value, o.value);
}
}
static final class Left extends Pair {
Left(int value) {
this.value = value;
}
@Override
public String toString() {
return "[" + value + ", _]";
}
}
static final class Right extends Pair {
Right(int value) {
this.value = value;
}
@Override
public String toString() {
return "[_, " + value + "]";
}
}
static final class Both extends Pair {
Both(int value) {
this.value = value;
}
@Override
public int hashCode() {
return value;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Both) {
return ((Both)obj).value == value;
}
return false;
}
@Override
public String toString() {
return "[" + value + ", " + value + "]";
}
}
@SuppressWarnings("unchecked")
@Test
public void test() {
Flowable<Integer> a = Flowable.just(0, 2, 3, 6);
Flowable<Integer> b = Flowable.just(1, 2, 3, 4, 5, 6);
Flowable.defer(() -> {
boolean[] skip = { false };
return Flowables.<Pair>orderedMerge(
a.<Pair>map(Left::new), b.<Pair>map(Right::new)
)
.distinctUntilChanged()
.buffer(2, 1)
.flatMapIterable(buf -> {
if (skip[0]) {
skip[0] = false;
return Collections.emptyList();
}
if (buf.size() == 2) {
if (buf.get(0).value == buf.get(1).value) {
skip[0] = true;
return Collections.singletonList(new Both(buf.get(0).value));
}
return buf.subList(0, 1);
}
return buf;
});
})
.subscribe(System.out::println);
}
where Flowables.orderedMerge
is in the RxJava 2 Extensions library.
来源:https://stackoverflow.com/questions/45220837/full-outer-join-of-two-ordered-observables