使用window()使用RxJava进行速率限制

时间:2020-02-21 15:32:19

标签: rx-java reactivex

我正在尝试对地图的增量更新进行速率限制,但对发出整个地图不感兴趣-仅以特定间隔缓冲对地图的增量更新,表示为人口稀少的地图。我还想立即发布第一个更新。

我一直在使用window()和油门Latest()运算符。

这是我到目前为止最接近的。在我的情况下,累加器函数更类似于Map :: putAll,但是我在这里使用String串联作为示例:

        // Emit ~10 items per second, group into 1 second windows:
        Observable<Observable<String>> windows = Observable.range( 1, 100 )
            .concatMap( i -> Observable.just( i ).delay( 100L, TimeUnit.MILLISECONDS ))
            .map( String::valueOf )
            .window( 1, TimeUnit.SECONDS );

        // Accumulator:
        BiFunction<String, String, String> accumulator = ( s1, s2 ) -> s1 + "-" + s2;

        // From first window, return first item immediately and the last item with the
        // accumulator function applied:
        Observable<String> firstWindow = windows
                .concatMap( window -> window
                        .scan( accumulator )
                        .throttleLatest( Long.MAX_VALUE, TimeUnit.SECONDS, true ))
                .take( 2 );

        // From remaining windows, return the last item with the function applied only:
        Observable<String> remainingWindows = windows
                .skip( 1 )
                .concatMap(
                        window -> window
                            .scan( accumulator )
                            .lastOrError()
                            .toObservable() );

        // Print the results:
        firstWindow.concatWith( remainingWindows )
            .blockingSubscribe( System.out::println );

上面的内容几乎满足了我的需求,但是第二个和第三个发射之间有2秒的暂停:

1
// 1 second pause
1-2-3-4-5-6-7-8-9
// 2 second pause
10-11-12-13-14-15-16-17-18-19
// 1 second pause
20-21-22-23-24-25-26-27-28-29
// 1 second pause
// . . .

有人能想到一种更好的方法吗?


编辑: 好的,所以我似乎可以通过添加publish()和connect()调用以及删除其余Windows的skip(1)来使其工作:

        // Emit ~10 items per second, group into 1 second windows:
        ConnectableObservable<Observable<String>> windows = Observable.range( 1, 100 )
                .concatMap( i -> Observable.just( i ).delay( 100L, TimeUnit.MILLISECONDS ))
                .map( String::valueOf )
                .window( 1, TimeUnit.SECONDS )
                .publish();

        // Accumulator:
        BiFunction<String, String, String> accumulator = ( s1, s2 ) -> s1 + "-" + s2;

        // From first window, return first item immediately and the last item with the
        // accumulator function applied:
        Observable<String> firstWindow = windows
                .concatMap( window -> window
                        .scan( accumulator )
                        .throttleLatest( Long.MAX_VALUE, TimeUnit.SECONDS, true ))
                .take( 2 );

        // From remaining windows, return the last item with the function applied only:
        Observable<String> remainingWindows = windows
                .concatMap(
                        window -> window
                            .scan( accumulator )
                            .lastOrError()
                            .toObservable() );

        // Print the results:
        Observable<String> result = firstWindow.concatWith( remainingWindows ).share();
        result.subscribe( System.out::println );

        // Connect:
        windows.connect();
        result.blockingSubscribe();

还是很想听听是否有人有更好的方法或可以对这里发生的事情提供很好的见解。例如,为什么在剩余的Windows上不需要skip(1)?

0 个答案:

没有答案