Java 如何将两个已排序的观察值合并为一个已排序的观察值?

Java 如何将两个已排序的观察值合并为一个已排序的观察值?,java,system.reactive,rx-java,Java,System.reactive,Rx Java,鉴于: Integer[]arr1={1,5,9,17}; 整数[]arr2={1,2,3,6,7,12,15}; 可观测的o1=可观测的距离(arr1); 可观测的o2=可观测的(arr2); 如何获取包含1,1,2,3,5,6,7,9,12,15,17的可观察对象?编辑:如果要使用此选项,请参阅专业评论。有一个edge案例没有得到处理,我没有找到快速修复它的方法,所以我现在没有时间修复它 这里有一个C#中的解决方案,因为您有system.reactive标记 Integer[] arr1

鉴于:

Integer[]arr1={1,5,9,17};
整数[]arr2={1,2,3,6,7,12,15};
可观测的o1=可观测的距离(arr1);
可观测的o2=可观测的(arr2);

如何获取包含
1,1,2,3,5,6,7,9,12,15,17的可观察对象?

编辑:如果要使用此选项,请参阅专业评论。有一个edge案例没有得到处理,我没有找到快速修复它的方法,所以我现在没有时间修复它

这里有一个C#中的解决方案,因为您有
system.reactive
标记

Integer[] arr1 = {1, 5, 9, 17};
Integer[] arr2 = {1, 2, 3, 6, 7, 12, 15};
Observable<Integer> o1 = Observable.from(arr1);
Observable<Integer> o2 = Observable.from(arr2);

您可以对序列进行合并、排序和展平,但这会带来很大的开销:

static IObservable<int> MergeSortedHot(IObservable<int> a, IObservable<int> b)
{
    return Observable.Merge(
        a.Delay(x => b.FirstOrDefaultAsync(y => x <= y)),
        b.Delay(y => a.FirstOrDefaultAsync(x => y <= x)));
}

否则,您需要编写一个相当复杂的运算符

编辑2015年6月4日:


一个更有效地执行此排序合并的运算符。

这是不久前在上讨论过的,您将在该线程中找到一些指向可能解决方案的链接。

我还在寻找一个支持反向压力的合并排序解决方案,但找不到它。因此,我决定在现有zip操作符的基础上自行实现它

与zip类似,排序合并操作符首先从每个可观察的源收集一个项目,然后将其放入优先级队列,然后根据其自然顺序或指定的比较器逐个发出

您可以从GitHub获取它作为一个随时可用的库,或者复制/粘贴代码:


有关用法,请参阅单元测试。

合并和排序怎么样

o1.concatWith(o2).toSortedList().flatMapIterable(v -> v).subscribe(...)
@测试
公共void testMergeChains(){
合并(Observable.from(Arrays.asList(1,2,13,11,5)),Observable.from(Arrays.asList(10,4,12,3,14,15)))
.collect(ArrayList::new,ArrayList::add)
.doOnNext(集合::排序)
.subscribe(System.out::println);
}
你可以在这里看到更多的例子


使用Kotlin中编写的自定义转换器的我的解决方案:

变压器:

@Test
public void testMergeChains() {
    Observable.merge(Observable.from(Arrays.asList(1, 2, 13, 11, 5)), Observable.from(Arrays.asList(10, 4, 12, 3, 14, 15)))
              .collect(ArrayList<Integer>::new, ArrayList::add)
            .doOnNext(Collections::sort)
            .subscribe(System.out::println);

}

非常有趣的问题,我喜欢。:)当使用
Observable.Create
创建一个可观察对象时,它似乎不起作用。我给gist举了一个例子:@the_joric是的,当一个可观察对象在另一个被订阅之前完成时,它看起来不起作用。不过,我现在没有时间来解决这个问题,所以我只想指出你的评论。这个解决方案很有效,但不幸的是,在数据量巨大的情况下,它效率低下:因为sort(),它需要消耗所有流并存储在内存中。在自述文件中,它说“你可以合并排序非常大或无限的排序序列”. 我认为这是相对于其他解决方案的主要优势。你应该强调一下。
o1.concatWith(o2).toSortedList().flatMapIterable(v -> v).subscribe(...)
@Test
public void testMergeChains() {
    Observable.merge(Observable.from(Arrays.asList(1, 2, 13, 11, 5)), Observable.from(Arrays.asList(10, 4, 12, 3, 14, 15)))
              .collect(ArrayList<Integer>::new, ArrayList::add)
            .doOnNext(Collections::sort)
            .subscribe(System.out::println);

}
fun <T> orderedMerge(f2: Flowable<T>, c: Comparator<T>) = FlowableTransformer<T, T> { f1 ->
    val f1Iterator = f1.blockingIterable(1).iterator()
    val f2Iterator = f2.blockingIterable(1).iterator()
    Flowable.generate(
            Callable { null as T? to null as T? },
            BiFunction { (lastF1: T?, lastF2: T?), emitter: Emitter<T> ->
                when {
                    lastF1 != null && f2Iterator.hasNext() -> {
                        val nextF2 = f2Iterator.next()
                        if (c.compare(lastF1, nextF2) <= 0) {
                            emitter.onNext(lastF1)
                            null to nextF2
                        } else {
                            emitter.onNext(nextF2)
                            lastF1 to null
                        }
                    }
                    lastF1 != null -> {
                        emitter.onNext(lastF1)
                        null to null
                    }
                    lastF2 != null && f1Iterator.hasNext() -> {
                        val nextF1 = f1Iterator.next()
                        if (c.compare(nextF1, lastF2) <= 0) {
                            emitter.onNext(nextF1)
                            null to lastF2
                        } else {
                            emitter.onNext(lastF2)
                            nextF1 to null
                        }
                    }
                    lastF2 != null -> {
                        emitter.onNext(lastF2)
                        null to null
                    }
                    f1Iterator.hasNext() && f2Iterator.hasNext() -> {
                        val nextF1 = f1Iterator.next()
                        val nextF2 = f2Iterator.next()
                        if (c.compare(nextF1, nextF2) <= 0) {
                            emitter.onNext(nextF1)
                            null to nextF2
                        } else {
                            emitter.onNext(nextF2)
                            nextF1 to null
                        }
                    }
                    f1Iterator.hasNext() -> {
                        val nextF1 = f1Iterator.next()
                        emitter.onNext(nextF1)
                        null to null
                    }
                    f2Iterator.hasNext() -> {
                        val nextF2 = f2Iterator.next()
                        emitter.onNext(nextF2)
                        null to null
                    }
                    else -> {
                        emitter.onComplete()
                        null to null
                    }
                }
            })
}
val f1 = listOf(1, 2, 3, 7, 10, 11, 11, 20).toFlowable()
val f2 = listOf(3, 4, 5, 8, 15, 16).toFlowable()

val ff = f1.compose(orderedMerge(f2, Comparator.naturalOrder()))